【Shiro权限管理】四、JdbcRealm、多Realm和Authentication Strategy验证策略

一、ini配置文件讲解

ini 配置文件类似于 Java 中的 properties(key=value),不过提供了将 key/value 分类的特性,key 是每个部分不重复即可,而不是整个配置文件。

  1. 使用Shiro 框架来完成认证工作默认情况下是使用iniRealm。如果需要其他Realm,那么需要进行相关配置。
  2. Ini配置文件讲解

      [main] Section 是配置SecurityManager实例及其他任何依赖组件(如:Realm)的地方。

[main]

MyRealm=com.study.Realm.MyRealm

#依赖注入

SecurityManager..realm=$MyRealm

      [users]section 允许你定义一组静态的用户账户。

[users]

zhansan=123,role1,role2

Lisi=123

     [roles]section 允许你把定义在[users]section中的角色与账户权限关联起来。

 

[roles]

Role1=zhansan:add,user2:detele

 

二、使用单JdbcRealm来完成身份验证。

 1、使用idea创建由Maven管理的Java工程。

 2、在POM依赖文件中加入依赖。

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.9</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.21</version>
        </dependency>

        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.4.0</version>
        </dependency>

        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>
        <!--连接池-->
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
        </dependency>
        <!--mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.32</version>
        </dependency>
    </dependencies>

此处因为我们需要访问数据库查询数据,所以要加入mysql驱动和连接池依赖。

3、加入Log4.properties日志文件

log4j.rootLogger=INFO,CONSOLE,A
log4j.addivity.org.apache=false

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.Threshold=INFO
log4j.appender.CONSOLE.layout.ConversionPattern=%d{yyyy-MM-dd HH\:mm\:ss} -%-4r [%t] %-5p  %x - %m%n
log4j.appender.CONSOLE.Target=System.out
log4j.appender.CONSOLE.Encoding=UTF-8
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout

log4j.appender.A=org.apache.log4j.DailyRollingFileAppender  
log4j.appender.A.File=${catalina.home}/logs/qdexam_log/qdexam_
log4j.appender.A.DatePattern=yyyy-MM-dd'.log'
log4j.appender.A.layout=org.apache.log4j.PatternLayout  
log4j.appender.A.layout.ConversionPattern=[qdexam_sys_log]  %d{yyyy-MM-dd HH\:mm\:ss} %5p %c{1}\:%L \: %m%n

4、观察JdbcRealm

public class JdbcRealm extends AuthorizingRealm {
    protected static final String DEFAULT_AUTHENTICATION_QUERY = "select password from users where username = ?";
    protected static final String DEFAULT_SALTED_AUTHENTICATION_QUERY = "select password, password_salt from users where username = ?";
    protected static final String DEFAULT_USER_ROLES_QUERY = "select role_name from user_roles where username = ?";
    protected static final String DEFAULT_PERMISSIONS_QUERY = "select permission from roles_permissions where role_name = ?";
    private static final Logger log = LoggerFactory.getLogger(JdbcRealm.class);
    protected DataSource dataSource;
    protected String authenticationQuery = "select password from users where username = ?";
    protected String userRolesQuery = "select role_name from user_roles where username = ?";
    protected String permissionsQuery = "select permission from roles_permissions where role_name = ?";
    protected boolean permissionsLookupEnabled = false;
    protected JdbcRealm.SaltStyle saltStyle;

我们发现Shiro为我们定义了许多SQL查询语句。所以我们应该创建此类的对象,并按照SQL语句中的数据表名和字段名创建数据库表。

其中password_salt为加密盐,后面篇文章会讲解。

5、编写测试代码,配置ini文件

1、首先看一下整个工程的目录结构。

2、编写代码

package com.study.shiro;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
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;

/**
 * @author James
 * @create 2019-10-27 22:03
 * 
 *
 */
public class JdbcRealmDemo {

    public static void main(String[] args){

        Factory<SecurityManager> factory=new IniSecurityManagerFactory("classpath:shiro.ini");

        SecurityManager securityManager = factory.getInstance();

        SecurityUtils.setSecurityManager(securityManager);

        Subject subject = SecurityUtils.getSubject();

        UsernamePasswordToken token=new UsernamePasswordToken("wangwu","1111");


        try {
            subject.login(token);
            if (subject.isAuthenticated()){
                System.out.println("验证通过...");
            }
        } catch (AuthenticationException e) {
            System.out.println("验证失败...");

        }
    }

}

3、配置ini文件

   3.1为JdbcRealm设置dataSource。

[main]
#配置数据源
dataSource=com.mchange.v2.c3p0.ComboPooledDataSource
dataSource.driverClass=com.mysql.jdbc.Driver
dataSource.jdbcUrl=jdbc:mysql://localhost:3306/sxt_shiro
dataSource.user=root
dataSource.password=123456
#配置Realm对象
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm

# $表示引用/注入对象
#为jdbcRealm注入dataSource
jdbcRealm.dataSource=$dataSource
#为securityManager注入realm
securityManager.realm=$jdbcRealm

测试代码中 我们的用户名/密码是wangwu,1111,数据库中有此用户,断言会验证通过。

此时我将密码改为:1234,再进行认证。

 UsernamePasswordToken token=new UsernamePasswordToken("wangwu","1234");
"C:\Program Files\Java\jdk1.8.0_191\bin\java.exe" "-javaagent:D:\idea\IntelliJ IDEA 2018.3.1\lib\idea_rt.jar=56015:D:\idea\IntelliJ IDEA 2018.3.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_191\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\rt.jar;D:\idea_workspace\sxt\shiro\shiro02_shior_JdbcRealm\target\classes;D:\Maven-3.5.2\LocalRespMaven\maven_repository\junit\junit\4.9\junit-4.9.jar;D:\Maven-3.5.2\LocalRespMaven\maven_repository\org\hamcrest\hamcrest-core\1.1\hamcrest-core-1.1.jar;D:\Maven-3.5.2\LocalRespMaven\maven_repository\org\slf4j\slf4j-log4j12\1.7.21\slf4j-log4j12-1.7.21.jar;D:\Maven-3.5.2\LocalRespMaven\maven_repository\org\slf4j\slf4j-api\1.7.21\slf4j-api-1.7.21.jar;D:\Maven-3.5.2\LocalRespMaven\maven_repository\log4j\log4j\1.2.17\log4j-1.2.17.jar;D:\Maven-3.5.2\LocalRespMaven\maven_repository\org\apache\shiro\shiro-core\1.4.0\shiro-core-1.4.0.jar;D:\Maven-3.5.2\LocalRespMaven\maven_repository\org\apache\shiro\shiro-lang\1.4.0\shiro-lang-1.4.0.jar;D:\Maven-3.5.2\LocalRespMaven\maven_repository\org\apache\shiro\shiro-cache\1.4.0\shiro-cache-1.4.0.jar;D:\Maven-3.5.2\LocalRespMaven\maven_repository\org\apache\shiro\shiro-crypto-hash\1.4.0\shiro-crypto-hash-1.4.0.jar;D:\Maven-3.5.2\LocalRespMaven\maven_repository\org\apache\shiro\shiro-crypto-core\1.4.0\shiro-crypto-core-1.4.0.jar;D:\Maven-3.5.2\LocalRespMaven\maven_repository\org\apache\shiro\shiro-crypto-cipher\1.4.0\shiro-crypto-cipher-1.4.0.jar;D:\Maven-3.5.2\LocalRespMaven\maven_repository\org\apache\shiro\shiro-config-core\1.4.0\shiro-config-core-1.4.0.jar;D:\Maven-3.5.2\LocalRespMaven\maven_repository\org\apache\shiro\shiro-config-ogdl\1.4.0\shiro-config-ogdl-1.4.0.jar;D:\Maven-3.5.2\LocalRespMaven\maven_repository\commons-beanutils\commons-beanutils\1.9.3\commons-beanutils-1.9.3.jar;D:\Maven-3.5.2\LocalRespMaven\maven_repository\commons-collections\commons-collections\3.2.2\commons-collections-3.2.2.jar;D:\Maven-3.5.2\LocalRespMaven\maven_repository\org\apache\shiro\shiro-event\1.4.0\shiro-event-1.4.0.jar;D:\Maven-3.5.2\LocalRespMaven\maven_repository\commons-logging\commons-logging\1.2\commons-logging-1.2.jar;D:\Maven-3.5.2\LocalRespMaven\maven_repository\c3p0\c3p0\0.9.1.2\c3p0-0.9.1.2.jar;D:\Maven-3.5.2\LocalRespMaven\maven_repository\mysql\mysql-connector-java\5.1.32\mysql-connector-java-5.1.32.jar" com.study.shiro.JdbcRealmDemo
2019-11-05 23:29:54 -15   [main] INFO    - MLog clients using log4j logging.
2019-11-05 23:29:54 -200  [main] INFO    - Initializing c3p0-0.9.1.2 [built 21-May-2007 15:04:56; debug? true; trace: 10]
2019-11-05 23:29:54 -316  [main] INFO    - Realms have been explicitly set on the SecurityManager instance - auto-setting of realms will not occur.
2019-11-05 23:29:54 -363  [main] INFO    - Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> 1b61bmla6gp6qxi1f6t08z|38082d64, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 1b61bmla6gp6qxi1f6t08z|38082d64, idleConnectionTestPeriod -> 0, initialPoolSize -> 3, jdbcUrl -> jdbc:mysql://localhost:3306/sxt_shiro, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 15, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 3, numHelperThreads -> 3, numThreadsAwaitingCheckoutDefaultUser -> 0, preferredTestQuery -> null, properties -> {user=******, password=******}, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false ]
验证失败...

三、多Realm进行认证。

使用多Realm,就可以看做多个数据库(多个dataSource)。所以我们只需在ini文件中配置多个dataSource就行。

1、在这里我新建了一个数据库shiro1,数据表的字段还是和第一个数据库中的users表字段一模一样,只是新增了lisi这个用户。

 

2、在ini文件中增加dataSource2。指向数据库shiro1。


[main]
#配置数据源
dataSource=com.mchange.v2.c3p0.ComboPooledDataSource
dataSource.driverClass=com.mysql.jdbc.Driver
dataSource.jdbcUrl=jdbc:mysql://localhost:3306/sxt_shiro
dataSource.user=root
dataSource.password=123456
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
#  $表示引用对象
jdbcRealm.dataSource=$dataSource



#配置数据源2
dataSource2=com.mchange.v2.c3p0.ComboPooledDataSource
dataSource2.driverClass=com.mysql.jdbc.Driver
dataSource2.jdbcUrl=jdbc:mysql://localhost:3306/sxt_shiro1
dataSource2.user=root
dataSource2.password=123456
jdbcRealm2=org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm2.dataSource=$dataSource2



securityManager.realms=$jdbcRealm,$jdbcRealm2



#配置策略
#AllSuccessfulStrategy:所有Realm验证成功才算成功,且返回所有Realm身份认证成功的认证信息,如果有一个失败就失败了
#配置验证器
authenticationStrategy=org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy
securityManager.authenticator.authenticationStrategy=$authenticationStrategy

3、多Realm认证就涉及到了验证策略。

       Authenticating Strategy 认证策略

     认证策略实际上是AuthenticationStrategy这个接口,它有三个实现:

     (1)FirstSuccessfulStrategy:只要有一个Realm验证成功即可,只返回第一个Realm身份验证成功的认证信息,其他的忽略。

     (2)AtLeatOneSuccessfulStrategy:只要有一个Realm验证成功即可,和FirstSuccessfulStrategy不同,AtLeatOneSuccessfulStrategy将返回所有Realm身份校验成功的认证信息。

     (3)AllSuccessfulStrategy:所有Realm验证成功才算成功,且返回所有Realm身份认证成功的认证信息,如果有一个失败就失败了。

    我们之前使用的ModularRealmAuthenticator默认是AtLeatOneSuccessfulStrategy。

 1、   在这里我们使用AtLeatOneSuccessfulStrategy: lisi 用户 就能认证成功。

2、在这里我们使用AllSuccessfulStrategy:lisi 就会失败。

至此 我们的JdbcRealm,和验证策略就到此结束了。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

真香号

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值