• shiro学习笔记_0300_jdbcRealm和认证策略


    使用shiro框架来完成认证工作,默认是iniRealm,如果需要使用其他的realm,需要配置。

    ini配置文件详解,官方文档的说明如下:

    [main] section 是你配置应用程序的 SecurityManager 实例及任何它的依赖组件(如 Realms)的地方。

    在[main]里 使用 键/值对 配置对象实例,如 SecurityManager 或任何它的依赖组件,如自定义的realm。

    如自定义一个realm,然后注入给SecurityManager:

    注:(在SecurityManager的实现类RealmSecurityManager中就可以setRealm)

    [main]
    myRealm=com.lhy.realm.MyRealm
    #依赖注入(类似spring)通过$引用
    securityManager.realm=$myRealm

    上边的配置就会创建id为myRealm的对象,然后把它赋给SecurityManager,类似spring的依赖注入

    [users] section 允许你定义一组静态的用户帐户。这在大部分拥有少数用户帐户或用户帐户不需要在运行时被动态地
    创建的环境下是很有用的。

    [users]
    zhangsan=1111
    lisi=1111,role1,role2

    [roles] section 允许你把定义在[users] section 中的角色与权限关联起来。另外,这在大部分拥有少数用户帐户或用户帐户不需要在运行时被动态地创建的环境下是很有用的

    [users]
    zhangsan=123,role1
    [roles]
    role1=user:add,user:delete   #role1是对user有add和delete权限
    
    

    规则:“用户名=密码,角色1,角色2”“角色=权限1,权限2”,即首先根据用户名找到角色,然后根据角色再找到权限;即角色是权限集合;Shiro同样不进行权限的维护,需要我们通过Realm返回相应的权限信息。只需要维护“用户——角色”之间的关系即可。

    2,使用JdbcRealm来完成身份认证

    通过观察JdbcRealm可知,要实现jdbcRealm:

      a)需要为jdbcRealm设置dataSource

      b)在指定的dataSource所对应的数据库表中有用户表users,该表中有username,password,password_salt (盐)等字段。

    =================================================================================

    shiro.ini配置文件:使用c3p0数据库连接池,注意c3p0和mysql驱动版本的匹配,mysql驱动版本不能太高,否则会报错的。我第一次使用的驱动是6.X的就报错说不匹配!

    
    

    [main]
    #配置数据源,使用c3p0连接池
    dataSource=com.mchange.v2.c3p0.ComboPooledDataSource
    dataSource.driverClass=com.mysql.jdbc.Driver
    dataSource.jdbcUrl=jdbc:mysql://localhost:3306/shiro
    dataSource.user=root
    dataSource.password=root
    jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
    #依赖注入,$表示引用对象
    jdbcRealm.dataSource=$dataSource
    securityManager.realm=$jdbcRealm

     

    新建数据库shiro,新建表users:并建立username,password,password_salt字段

    还是使用maven项目,添加c3p0,mysql的依赖:

        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.2</version>
        </dependency>
        
        <dependency> 
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.31</version>
        </dependency>

    新建测试类  JdbcRealm.java:

    package com.lhy.shiro;
    
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.AuthenticationException;
    import org.apache.shiro.authc.IncorrectCredentialsException;
    import org.apache.shiro.authc.UnknownAccountException;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.config.IniSecurityManagerFactory;
    import org.apache.shiro.mgt.SecurityManager;
    import org.apache.shiro.subject.Subject;
    import org.apache.shiro.util.Factory;
    
    public class JdbcRealmDemo { 
    
        public static void main(String[] args) {
            //1,创建SecurityManager工厂  读取shiro配置文件
            Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
            //2  通过securityManager工厂获取SecurityManager实例
            SecurityManager securityManager = factory.getInstance();
            //3 将SecurityManager 对象设置到运行环境
            SecurityUtils.setSecurityManager(securityManager);
            //4 通过SecurityUtils获取主体subject
            Subject subject = SecurityUtils.getSubject();
            try {
                //5.假设登录名是zhangsan  密码是1111
                UsernamePasswordToken token = new UsernamePasswordToken("niubei","1111");
                //6,登录,进行用户身验证 
                subject.login(token);
                //通过subject判断用户是否通过验证
                if(subject.isAuthenticated()){
                    System.out.println("用户登录成功!"); 
                }
            } catch (UnknownAccountException e) {     
                System.out.println("用户名或密码错误!"); 
                e.printStackTrace();
            }catch (IncorrectCredentialsException e) {
                System.out.println("用户名或密码错误!");
                e.printStackTrace();
            }
            //其他异常处理。。。
            //7 退出
            subject.logout();   
        
            
        }
    }

    shiro.ini里配置的是jdbcRealm,认证器就会调用jdbcRealm

    认证策略:AuthenticationStrategy

    当一个应用程序配置了两个或两个以上的 Realm 时,ModularRealmAuthenticator 依靠内部的AuthenticationStrategy 组件来确定这些认证尝试的成功或失败条件。

    shiro有三种认证策略:

     默认是第一个策略。

    subject.login(token)的执行过程,查看源代码:

    可知,subject.login(token)调用的是Subject接口的实现类DelegatingSubject的login方法,再查看securityManager.login(this,token):

    调用的是SecurityManager的实现类,DefaultSecurityManager的login方法。间接地调用的是其父类AuthenticatingSecurityManager的方法authenticate(token)将token传给认证器

    查看上图箭头所指的认证器,是AuthenticatingSecurityManager的一个属性,这个就是认证器接口

    shiro所用的就是认证器的实现类ModularRealmAuthenticator。查看这个实现类可知,里边就有一个认证策略接口,默认策略是AtLeastOneSuccessfulStrategy

    查看认证策略的类关系可知,他有三个认证策略。

    ======================================================================

    修改默认的认证策略,实验多Realm思路:ini配置文件里把数据源copy一份,模拟两个数据源:

    [main]
    #数据库连接池
    dataSource=com.mchange.v2.c3p0.ComboPooledDataSource
    dataSource.driverClass=com.mysql.jdbc.Driver
    dataSource.jdbcUrl=jdbc:mysql://localhost:3306/shiro
    dataSource.user=root
    dataSource.password=root
    jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
    #依赖注入 $表示引用对象
    jdbcRealm.dataSource=$dataSource
    #配置验证器
    authcStrategy = org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy
    #####################第二个数据源,一个数据源把这部分删除############
    dataSource1=com.mchange.v2.c3p0.ComboPooledDataSource
    dataSource1.driverClass=com.mysql.jdbc.Driver
    dataSource1.jdbcUrl=jdbc:mysql://localhost:3306/shiro1
    dataSource1.user=root
    dataSource1.password=root
    jdbcRealm1=org.apache.shiro.realm.jdbc.JdbcRealm
    jdbcRealm1.dataSource=$dataSource1
    ##################################################################
    securityManager.realms=$jdbcRealm
    securityManager.authenticator.authenticationStrategy = $authcStrategy

    然后再新建一个数据库shiro1,新建users表进行试验。在此我就不做实验了。用到了再说。

  • 相关阅读:
    mybatis中resultMap配置细则
    关于mybatis中typeHandler的两个案例
    Sharding模式
    Data Partitioning Guidance
    算法相关——Java排序算法之桶排序(一)
    Java并发——线程中断学习
    Android开发——ListView使用技巧总结(二)
    Android开发——ListView使用技巧总结(一)
    [原]Jenkins(十八) jenkins再出发之jenkins 内置变量
    [原]Jenkins(十七) jenkins再出发之配置SVN
  • 原文地址:https://www.cnblogs.com/lihaoyang/p/6580267.html
Copyright © 2020-2023  润新知