美文网首页
Shiro简单demo

Shiro简单demo

作者: dwwl | 来源:发表于2019-08-05 21:03 被阅读0次

    参考Blog :http://wiki.jikexueyuan.com/project/shiro/authentication.html

    执行流程:

    1. 首先调用 Subject.login(token) 进行登录,其会自动委托给 Security Manager,调用之前必须通过 SecurityUtils.setSecurityManager() 设置;

    2. SecurityManager 负责真正的身份验证逻辑;它会委托给 Authenticator 进行身份验证;

    3. Authenticator 才是真正的身份验证者,Shiro API 中核心的身份认证入口点,此处可以自定义插入自己的实现;

    4. Authenticator 可能会委托给相应的 AuthenticationStrategy 进行多 Realm 身份验证,默认 ModularRealmAuthenticator 会调用 AuthenticationStrategy 进行多 Realm 身份验证;

    5. Authenticator 会把相应的 token 传入 Realm,从 Realm 获取身份验证信息,如果没有返回 / 抛出异常表示身份验证失败了。此处可以配置多个 Realm,将按照相应的顺序及策略进行访问。

    6. public class MyRealm1 implements Realm {
          @Override
          public String getName() {
              return "myrealm1";
          }
          @Override
          public boolean supports(AuthenticationToken token) {
              //仅支持UsernamePasswordToken类型的Token
              return token instanceof UsernamePasswordToken; 
          }
          @Override
          public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
              String username = (String)token.getPrincipal();  //得到用户名
              String password = new String((char[])token.getCredentials()); //得到密码
              if(!"zhang".equals(username)) {
                  throw new UnknownAccountException(); //如果用户名错误
              }
              if(!"123".equals(password)) {
                  throw new IncorrectCredentialsException(); //如果密码错误
              }
              //如果身份认证验证成功,返回一个AuthenticationInfo实现;
              return new SimpleAuthenticationInfo(username, password, getName());
          }
      }
      
      img

    以后一般继承 AuthorizingRealm(授权)即可;其继承了 AuthenticatingRealm(即身份验证),而且也间接继承了 CachingRealm(带有缓存实现)。

    JDBC Realm 使用

    最简单的对角色 权限进行控制的demo

    pom.xml

    <?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>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.1.6.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.mpt</groupId>
        <artifactId>bootshirodemo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>bootshirodemo</name>
        <description>Demo project for Spring Boot</description>
    
        <properties>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>2.1.0</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-spring-boot-starter</artifactId>
                <version>1.4.0</version>
            </dependency>
            <!-- fastjson -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.47</version>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    </project>
    
    

    application.yml

    spring:
      datasource:
        url: jdbc:mysql://localhost:3306/mydb?serverTimezone=GMT
        driver-class-name: com.mysql.jdbc.Driver
        username: root
        password:
      main:
        allow-bean-definition-overriding: true
    server:
      port: 9001
      tomcat:
        uri-encoding: utf-8
    mybatis:
      mapper-locations: mappers/*Mapper.xml
    logging:
      level:
        com:
          mpt:
            bootshirodemo: DEBUG
    

    BootshirodemoApplication.java

    package com.mpt.bootshirodemo;
    
    import com.alibaba.fastjson.serializer.SerializerFeature;
    import com.alibaba.fastjson.support.config.FastJsonConfig;
    import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
    import org.springframework.context.annotation.Bean;
    import org.springframework.http.converter.HttpMessageConverter;
    
    @SpringBootApplication
    public class BootshirodemoApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(BootshirodemoApplication.class, args);
        }
    
        @Bean
        public HttpMessageConverters fastJsonHttpMessageConverters() {
            //1、定义一个convert转换消息的对象
            FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
            //2、添加fastjson的配置信息
            FastJsonConfig fastJsonConfig = new FastJsonConfig();
            fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
            //3、在convert中添加配置信息
            fastConverter.setFastJsonConfig(fastJsonConfig);
            //4、将convert添加到converters中
            HttpMessageConverter<?> converter = fastConverter;
            return new HttpMessageConverters(converter);
        }
    }
    

    这里用的fastJson用于mvc数据传输接收时 对象与json之间的转换,具体的现在还要学习一下。

    UserRealm.java

    package com.mpt.bootshirodemo.realm;
    
    import com.mpt.bootshirodemo.po.SysUser;
    import com.mpt.bootshirodemo.service.SysPermissionService;
    import com.mpt.bootshirodemo.service.SysUserService;
    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.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    import sun.java2d.pipe.SpanShapeRenderer;
    
    import java.util.HashSet;
    import java.util.List;
    
    /**
     * @author huangQiChang
     * @date 2019/8/5
     */
    @Component
    public class UserRealm extends AuthorizingRealm {
    
        private Logger logger = LoggerFactory.getLogger(UserRealm.class);
    
        @Autowired
        private SysUserService sysUserService;
    
        @Autowired
        private SysPermissionService sysPermissionService;
    
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
            logger.info("doGetAuthorizationInfo....");
            SysUser sysUSer = (SysUser) principals.getPrimaryPrincipal();
            List<String> permissions = sysPermissionService.selectPermissionByUserId(String.valueOf(sysUSer.getUserId()));
    
            HashSet<String> permissionsSet = new HashSet<>(permissions);
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
            info.setStringPermissions(permissionsSet);//setRoles方法用户设置用户所拥有的角色。
            return info;
        }
    
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
            SysUser sysUser = sysUserService.findByUserName(token.getUsername());
    
            if (sysUser == null) {
                return null;
            }
            logger.info("doGetAuthenticationInfo....");
            return new SimpleAuthenticationInfo(sysUser, sysUser.getPassword().toCharArray(), ByteSource.Util.bytes(sysUser.getSalt()), getName());
        }
    }
    
    

    ShiroConfig.java

    package com.mpt.bootshirodemo;
    
    import com.mpt.bootshirodemo.realm.UserRealm;
    import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
    import org.apache.shiro.mgt.SecurityManager;
    import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
    import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    /**
     * @Description
     * @Author sgl
     * @Date 2018-06-11 17:23
     */
    @Configuration
    public class ShiroConfig {
    
        /**
         * 凭证匹配器
         *
         * @return
         */
        @Bean
        public HashedCredentialsMatcher hashedCredentialsMatcher() {
            HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
            //md5加密1次
            hashedCredentialsMatcher.setHashAlgorithmName("md5");
            hashedCredentialsMatcher.setHashIterations(1);
            return hashedCredentialsMatcher;
        }
    
        /**
         * 自定义realm
         *
         * @return
         */
        @Bean
        public UserRealm userRealm() {
            UserRealm userRealm = new UserRealm();
            userRealm.setCredentialsMatcher(hashedCredentialsMatcher());
            return userRealm;
        }
    
        /**
         * 安全管理器
         * 注:使用shiro-spring-boot-starter 1.4时,返回类型是SecurityManager会报错,直接引用shiro-spring则不报错
         *
         * @return
         */
        @Bean
        public DefaultWebSecurityManager securityManager() {
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            securityManager.setRealm(userRealm());
            return securityManager;
        }
    
    
        /**
         * 设置过滤规则
         *
         * @param securityManager
         * @return
         */
        @Bean
        public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            shiroFilterFactoryBean.setSecurityManager(securityManager);
            shiroFilterFactoryBean.setLoginUrl("/login");
            shiroFilterFactoryBean.setSuccessUrl("/");
            shiroFilterFactoryBean.setUnauthorizedUrl("/unauth");
    
            //注意此处使用的是LinkedHashMap,是有顺序的,shiro会按从上到下的顺序匹配验证,匹配了就不再继续验证
            //所以上面的url要苛刻,宽松的url要放在下面,尤其是"/**"要放到最下面,如果放前面的话其后的验证规则就没作用了。
            Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
            filterChainDefinitionMap.put("/static/**", "anon");
            filterChainDefinitionMap.put("/login", "anon");
            filterChainDefinitionMap.put("/captcha.jpg", "anon");
            filterChainDefinitionMap.put("/favicon.ico", "anon");
            filterChainDefinitionMap.put("/**", "authc");
    
            shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
            return shiroFilterFactoryBean;
        }
    }
    

    TestController.java

    @RestController
    public class TestController {
    
    //    @RequiresRoles("普通用户")
        @RequiresPermissions("systemUserList")
        @GetMapping("/testPerm")
        public String testPerm() {
            return "存在menu权限";
        }
    }
    

    md5加密处理

    package com.mpt.bootshirodemo;
    
    import org.apache.shiro.crypto.hash.SimpleHash;
    import org.apache.shiro.util.ByteSource;
    
    /**
     * @author huangQiChang
     * @date 2019/8/5
     */
    public class ShiroMD5 {
        //加密方式
        private final static String HASHMODE = "Md5";
        //加密次数
        private final static int SALTNUM = 1;
    
        public static Object shiroMD5(String mySalt, String pwd) {
            String hashAlgorithmName = HASHMODE;
            //"123456";
            Object credentials = pwd;
            //以用户名作为盐加密
            Object salt = ByteSource.Util.bytes(mySalt);
            int hashIterations = SALTNUM;
            Object result = new SimpleHash(hashAlgorithmName, credentials, salt, hashIterations);
            return result;
        }
    
        public static void main(String[] args) {
            System.out.println(shiroMD5("1","1"));
        }
    }
    
    

    相关文章

      网友评论

          本文标题:Shiro简单demo

          本文链接:https://www.haomeiwen.com/subject/ssmvdctx.html