zoukankan      html  css  js  c++  java
  • shiro认证流程

    创建测试工程

    加入shiro-core的jar包及其依赖包

    与其它java开源框架类似,将shirojar包加入项目就可以使用shiro提供的功能了。shiro-core是核心包必须选用,还提供了与web整合的shiro-web、与spring整合的shiro-spring、与任务调度quartz整合的shiro-quartz等,下边是shirojar包的maven坐标。

    <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-core</artifactId>
                <version>1.3.2</version>
            </dependency>
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-web</artifactId>
                <version>1.3.2</version>
            </dependency>
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-spring</artifactId>
                <version>1.3.2</version>
            </dependency>
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-ehcache</artifactId>
                <version>1.3.2</version>
            </dependency>
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-quartz</artifactId>
                <version>1.3.2</version>
            </dependency>
    
    也可以通过引入shiro-all包括shiro所有的包:
        <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-all</artifactId>
                <version>1.3.2</version>
            </dependency>
    shiro各jar包的maven坐标

    创建工程目录

    shiro.ini

    通过Shiro.ini配置文件初始化SecurityManager环境。

     配置 eclipse支持ini文件编辑:

    eclipse配置后,在classpath创建shiro-realm.ini配置文件,为了方便测试将用户名和密码配置的shiro.ini配置文件中:

    [users]
    zhang=111111

    认证代码

    public class TestAhentication {
    
        @Test
        public void testLoginAndLogout() {
            
            // 构建SecurityManager工厂,IniSecurityManagerFactory可以从ini文件中初始化SecurityManager环境
            Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-realm.ini");
            
            // 通过工厂创建SecurityManager
            SecurityManager securityManager = factory.getInstance();
            
            // 将securityManager设置到运行环境中
            SecurityUtils.setSecurityManager(securityManager);
            
            // 创建一个Subject实例,该实例认证要使用上边创建的securityManager进行
            Subject subject = SecurityUtils.getSubject();
            
    //        AuthenticationToken arg0
            UsernamePasswordToken token = new UsernamePasswordToken("zhang","111111");
            
                try {
                    subject.login(token);
                } catch (AuthenticationException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            
            // 用户认证状态
            boolean isAuthenticated = subject.isAuthenticated();
            System.out.println("用户登录认证结果:"+isAuthenticated);
            
            //密码错误异常   org.apache.shiro.authc.IncorrectCredentialsException
            //账号错误异常 org.apache.shiro.authc.UnknownAccountException
            
            subject.logout();
            System.out.println("用户退出认证结果"+subject.isAuthenticated());
        }
    }

    常见的异常

     UnknownAccountException

    账号不存在异常如下:

    org.apache.shiro.authc.UnknownAccountException: Realm [org.apache.shiro.realm.text.IniRealm@7c75222b] was unable to find account data for the submitted AuthenticationToken [org.apache.shiro.authc.UsernamePasswordToken - zhang, rememberMe=false].

    IncorrectCredentialsException

    当输入密码错误会抛此异常,如下:

    org.apache.shiro.authc.IncorrectCredentialsException: Submitted credentials for token [org.apache.shiro.authc.UsernamePasswordToken - zhang, rememberMe=false] did not match the expected credentials.

    更多异常

    认证执行流程

    1、 创建token令牌,token中有用户提交的认证信息即账号和密码

    2、 执行subject.login(token),提交给securityManager (安全管理器),安全管理器在通过Authenticator进行认证,

    3、 Authenticator 安排ModularRealmAuthenticator调用realmini配置文件取用户真实的账号和密码,这里使用的是IniRealmshiro自带)

    4、 IniRealm先根据token中的账号去ini中找该账号,如果找不到则给ModularRealmAuthenticator返回null,如果找到则匹配密码,匹配密码成功则认证通过。

    通过token获取user的过程

     

    密码匹配的过程源码

     

    自定义Realm实现通过数据库查询数据

      上边的程序使用的是Shiro自带的IniRealmIniRealmini配置文件中读取用户的信息,大部分情况下需要从系统的数据库中读取用户信息,所以需要自定义realm

     shiro提供的realm

    最基础的是Realm接口,CachingRealm负责缓存处理,AuthenticationRealm负责认证,AuthorizingRealm负责授权,通常自定义的realm继承AuthorizingRealm

     创建自定义realm类

    public class CustomRealm extends AuthorizingRealm

     

    public class CustomRealm extends AuthorizingRealm{
    
        public void setName() {
            super.setName("customRealm");
        }
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token){
    
            //获取认证凭证
            UsernamePasswordToken upToken = (UsernamePasswordToken) token;
            String username = upToken.getUsername();
            
            if (username == null) {
                throw new AuthenticationException("账号为空");
            }
            //进行数据库查询账号信息
            
            //模拟数据库查询信息
            if (!username.equals("zhangsan1")) {
                return null;
            }
            //用户存在 获取到数据库的密码  返回出去
            //假设密码是1111
            String password = "1111";
            
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, password, getName());
            
            return info;
        }
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
            // TODO Auto-generated method stub
            return null;
        }
    }

    shiro-customRealm.ini

    [main]
    #自定义 realm
    customRealm=com.td.shiro.realm.CustomRealm
    #将realm设置到securityManager
    securityManager.realms=$customRealm

    进行测试

    @Test
        public void testLoginAndLogout1() {        
            // 构建SecurityManager工厂,IniSecurityManagerFactory可以从ini文件中初始化SecurityManager环境
            Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-customRealm.ini");
            // 通过工厂创建SecurityManager
            SecurityManager securityManager = factory.getInstance();
            // 将securityManager设置到运行环境中
            SecurityUtils.setSecurityManager(securityManager);
            // 创建一个Subject实例,该实例认证要使用上边创建的securityManager进行
            Subject subject = SecurityUtils.getSubject();
    //        AuthenticationToken arg0
            UsernamePasswordToken token = new UsernamePasswordToken("zhangsan","1111");
                try {
                    subject.login(token);
                } catch (AuthenticationException e) {
                    e.printStackTrace();
                }
            
            // 用户认证状态
            boolean isAuthenticated = subject.isAuthenticated();
            System.out.println("用户登录认证结果:"+isAuthenticated);
            //密码错误异常   org.apache.shiro.authc.IncorrectCredentialsException
            //账号错误异常 org.apache.shiro.authc.UnknownAccountException    
            subject.logout();
            System.out.println("用户退出认证结果"+subject.isAuthenticated());
        }
  • 相关阅读:
    ELK安装使用详细说明
    redis实现分布式锁来防止重复提交问题(redis锁)
    解决controller使用@Autowired注解注入为null问题
    oracle起定时任务
    线程池的4种拒绝策略
    线程池的3种队列区别和使用: ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue
    java Web 启动时自动执行代码的几种方式
    list集合去重的几种方式
    对List对象集合进行排序像sql的order by一样
    springboot进行动态数据源配置(基于注解方式)
  • 原文地址:https://www.cnblogs.com/lldsgj/p/10778867.html
Copyright © 2011-2022 走看看