• SpringBoot+Shiro入门小栗子


    写一个不花里胡哨的纯粹的Springboot+Shiro的入门小栗子

    效果如图:

    首页:有登录注册

    先注册一个,然后登陆

    登录,成功自动跳转到home页

    home页:通过认证之后才可以进

     


    代码部分:

    依赖:

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.example</groupId>
        <artifactId>demo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>jar</packaging>
    
        <name>demo</name>
        <description>Demo project for Spring Boot</description>
    
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.0.3.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-all -->
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-all</artifactId>
                <version>1.3.2</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.47</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/net.sf.ehcache/ehcache -->
            <dependency>
                <groupId>net.sf.ehcache</groupId>
                <artifactId>ehcache</artifactId>
                <version>2.10.5</version>
            </dependency>
    
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    
    </project>
    View Code

    Java配置类:

    package com.example.demo.conf;
    
    import com.example.demo.auth.PermissionRealm;
    import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
    import org.apache.shiro.cache.CacheManager;
    import org.apache.shiro.cache.ehcache.EhCacheManager;
    import org.apache.shiro.realm.AuthorizingRealm;
    import org.apache.shiro.spring.LifecycleBeanPostProcessor;
    import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
    import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
    import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.DependsOn;
    
    import java.util.LinkedHashMap;
    
    /**
     * @program: boot-shiro
     * @description:
     * @author: 001977
     * @create: 2018-07-17 18:22
     */
    @Configuration
    public class ShiroConfig {
    
        /**
         * 1. 配置SecurityManager
         * @return
         */
        @Bean
        public DefaultWebSecurityManager securityManager(){
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            securityManager.setRealm(realm());
            return securityManager;
        }
    
        /**
         * 2. 配置缓存
         * @return
         */
        @Bean
        public CacheManager cacheManager(){
            EhCacheManager ehCacheManager = new EhCacheManager();
            ehCacheManager.setCacheManagerConfigFile("classpath:ehcache.xml");
            return ehCacheManager;
        }
    
        /**
         * 3. 配置Realm
         * @return
         */
        @Bean
        public AuthorizingRealm realm(){
            PermissionRealm realm = new PermissionRealm();
            HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
            // 指定加密算法
            matcher.setHashAlgorithmName("MD5");
            // 指定加密次数
            matcher.setHashIterations(10);
            // 指定这个就不会报错
            matcher.setStoredCredentialsHexEncoded(true);
            realm.setCredentialsMatcher(matcher);
            return realm;
        }
    
        /**
         * 4. 配置LifecycleBeanPostProcessor,可以来自动的调用配置在Spring IOC容器中 Shiro Bean 的生命周期方法
         * @return
         */
        @Bean
        public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
            return new LifecycleBeanPostProcessor();
        }
    
        /**
         * 5. 启用IOC容器中使用Shiro的注解,但是必须配置第四步才可以使用
         * @return
         */
        @Bean
        @DependsOn("lifecycleBeanPostProcessor")
        public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
            return new DefaultAdvisorAutoProxyCreator();
        }
    
        /**
         * 6. 配置ShiroFilter
         * @return
         */
        @Bean
        public ShiroFilterFactoryBean shiroFilterFactoryBean(){
            LinkedHashMap<String, String> map = new LinkedHashMap<>();
            // 静态资源
            map.put("/css/**", "anon");
            map.put("/js/**", "anon");
    
            // 公共路径
            map.put("/login", "anon");
            map.put("/register", "anon");
            //map.put("/*", "anon");
    
            // 登出,项目中没有/logout路径,因为shiro是过滤器,而SpringMVC是Servlet,Shiro会先执行
            map.put("/logout", "logout");
    
            // 授权
            map.put("/user/**", "authc,roles[user]");
            map.put("/admin/**", "authc,roles[admin]");
    
            // everything else requires authentication:
            map.put("/**", "authc");
    
            ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
            // 配置SecurityManager
            factoryBean.setSecurityManager(securityManager());
            // 配置权限路径
            factoryBean.setFilterChainDefinitionMap(map);
            // 配置登录url
            factoryBean.setLoginUrl("/");
            // 配置无权限路径
            factoryBean.setUnauthorizedUrl("/unauthorized");
            return factoryBean;
        }
    
    }

     Realm类:

    package com.example.demo.auth;
    
    import com.example.demo.common.entity.User;
    import com.example.demo.service.UserService;
    import org.apache.shiro.authc.*;
    import org.apache.shiro.authz.AuthorizationInfo;
    import org.apache.shiro.authz.SimpleAuthorizationInfo;
    import org.apache.shiro.realm.AuthorizingRealm;
    import org.apache.shiro.subject.PrincipalCollection;
    import org.apache.shiro.util.ByteSource;
    import org.springframework.beans.factory.annotation.Autowired;
    
    import java.util.HashSet;
    import java.util.Set;
    
    /**
     * @program: boot-shiro
     * @description:
     * @author: 001977
     * @create: 2018-07-12 13:03
     */
    public class PermissionRealm extends AuthorizingRealm {
    
        @Autowired
        private UserService userService;
    
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            Object principal = principalCollection.getPrimaryPrincipal();
            User user = (User) principal;
            Set<String> roles = new HashSet<>();
            roles.add("user");
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roles);
            return info;
        }
    
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            UsernamePasswordToken uToken = (UsernamePasswordToken) authenticationToken;
    
            String username = uToken.getUsername();
            String password = String.valueOf(uToken.getPassword());
    
            User user = userService.login(new User(username,password));
    
            if(user == null){
                throw new AuthenticationException("用户名密码不存在");
            }
            //认证的实体信息
            Object principal = user;
            //从数据库获取的密码
            Object hashedCredentials = user.getPassword();
            //盐值
            ByteSource credentialsSalt = ByteSource.Util.bytes(user.getUsername());
            //当前Realm对象的name,调用父类的getName方法
            String realmName = getName();
    
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal, hashedCredentials, credentialsSalt, realmName);
    
            return info;
        }
    }

    Controller:

    package com.example.demo.controller;
    
    import com.example.demo.common.TempStorage;
    import com.example.demo.common.entity.User;
    import com.example.demo.common.response.BaseResponse;
    import com.example.demo.service.UserService;
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.subject.Subject;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.servlet.ModelAndView;
    
    /**
     * @program: boot-shiro
     * @description:
     * @author: 001977
     * @create: 2018-07-12 13:02
     */
    @RestController
    public class SimpleController {
    
        @Autowired
        private UserService userService;
    
        @RequestMapping("/")
        public ModelAndView index(){
            return new ModelAndView("index");
        }
    
        @RequestMapping("/login")
        public BaseResponse<String> login(@RequestBody User user){
            BaseResponse<String> response = new BaseResponse<>(0,"登陆成功");
            Subject subject = SecurityUtils.getSubject();
            UsernamePasswordToken token = new UsernamePasswordToken(
                    user.getUsername(), user.getPassword());
            subject.login(token);
            response.setData("/home");
            return response;
        }
    
        @RequestMapping("/register")
        public BaseResponse register(@RequestBody User user){
            userService.addUser(user);
            return new BaseResponse(0,"注册成功");
        }
    
        @RequestMapping("/home")
        public ModelAndView home(){
            ModelAndView mv = new ModelAndView("home");
            mv.addObject("users", TempStorage.getInstance().getMap());
            return mv;
        }
    }

    其余代码参见GitHub

  • 相关阅读:
    LeetCode 24. Swap Nodes in Pairs
    LeetCode 02.07. Intersection of Two Linked Lists LCCI
    LeetCode 707. Design Linked List
    centos7 mail
    centos7 安装postgresql10
    centos 7 安装 mail
    解决运行docker命令要用sudo的问题
    Linux 命令速记本
    iterm2配置lrzsz
    截取某段时间内的日志
  • 原文地址:https://www.cnblogs.com/LUA123/p/9328922.html
Copyright © 2020-2023  润新知