学习shiro第三天
今天比较晚,所以只看了shiro的认证策略Authentication Strategy,下面讲讲shiro的三种认证策略。
1.AtLeastOneSuccessfulStrategy:这个是shiro默认的认证策略,它表示如果存在多个realm来执行认证,只要其中有一个成功,那么认证就成功(这里注意所有的realm都会进行验证,不管是失败还是成功);
2.AllSuccessfulStrategy:这个策略表示必须所有的realm认证成功才算最终认证成功,哪怕只有一个不成功,那么结果都为认证不成功。(这里也是会将所有的realm都进行验证);
3.FirstSuccessfulStrategy:它表示只要有一个realm中认证成功了,那么剩下的其它realm都不必进行验证了,直接返回认证成功。注意这里只要遇到第一个成功认证的realm,其他剩下的realm都不会被调用。
说了三种认证策略的概念,那么我们怎么进行配置认证策略呢?这个问题就要追溯到shiro中进行认证操作的认证器子类modularRealmAuthenticator,它里面有一个属性authenticationStrategy,并且
modularRealmAuthenticator在它的构造函数中将这个属性默认设置成new AtLeastOneSuccessfulStrategy():
private AuthenticationStrategy authenticationStrategy; /*--------------------------------------------
| C O N S T R U C T O R S |
============================================*/ /**
* Default no-argument constructor which
* {@link #setAuthenticationStrategy(AuthenticationStrategy) enables} an
* {@link org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy} by default.
*/
public ModularRealmAuthenticator() {
this.authenticationStrategy = new AtLeastOneSuccessfulStrategy();
}
所有我们要配置认证策略,只需要配置modularRealmAuthenticator类中的authenticationStrategy属性。下面是配置认证策略的过程:
[main]
dataSource=com.mchange.v2.c3p0.ComboPooledDataSource
dataSource.driverClass=com.mysql.jdbc.Driver
dataSource.jdbcUrl=jdbc:mysql://localhost:3306/test
dataSource.user=root
dataSource.password=root
myRealm=org.apache.shiro.realm.jdbc.JdbcRealm
myRealm.dataSource=$dataSource dataSource1=com.mchange.v2.c3p0.ComboPooledDataSource
dataSource1.driverClass=com.mysql.jdbc.Driver
dataSource1.jdbcUrl=jdbc:mysql://localhost:3306/test1
dataSource1.user=root
dataSource1.password=root
myRealm1=org.apache.shiro.realm.jdbc.JdbcRealm
myRealm1.dataSource=$dataSource1
#配置认证策略
authenticator=org.apache.shiro.authc.pam.ModularRealmAuthenticator
authenticationStrategy=org.apache.shiro.authc.pam.FirstSuccessfulStrategy
authenticator.authenticationStrategy=$authenticationStrategy
securityManager.authenticator=$authenticator
securityManager.realms=$myRealm,$myRealm1
在配置认证策略中,我将认证策略配成了FirstSuccessFulStrategy,然后将这个配置了新的认证策略的认证器赋予了SecurityManager中的authenticator属性从而完成了认证策略的配置。为了测试这几个策略的区别,我在shiro.ini文件中又创建了一个realm,并注入了一个新的数据源:
两个数据库中都有users的表,但是数据并不相同。下面开始认证编码,还是那一套流程:
package test_JdbcRealm; 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;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; public class TestAuthencationStrategy { private static final Logger logger = LoggerFactory.getLogger(TestAuthencationStrategy.class); public static void main(String[] args) {
//1.创建securityManager工厂
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
//2.获取securityManager实例
SecurityManager securityManager = factory.getInstance();
//3.将SecurityManager实例设置到SecurityUtils工具类中
SecurityUtils.setSecurityManager(securityManager);
//4。创建Subject实例
Subject subject = SecurityUtils.getSubject();
//5.获取token,模拟用户登陆
UsernamePasswordToken token = new UsernamePasswordToken("wangwu", "456789");
try {
//6.认证token
subject.login(token);
if(subject.isAuthenticated()) {
logger.info("登陆成功");
}
} catch (AuthenticationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
logger.error("用户名或密码错误,登陆失败");
}
}
}
运行控制台输出如下:
2019-07-26 23:54:32,756 INFO [com.mchange.v2.log.MLog] - MLog clients using slf4j logging.
2019-07-26 23:54:33,216 INFO [com.mchange.v2.c3p0.C3P0Registry] - Initializing c3p0-0.9.5.2 [built 08-December-2015 22:06:04 -0800; debug? true; trace: 10]
2019-07-26 23:54:33,344 INFO [org.apache.shiro.config.IniSecurityManagerFactory] - Realms have been explicitly set on the SecurityManager instance - auto-setting of realms will not occur.
2019-07-26 23:54:33,373 INFO [com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource] - 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, contextClassLoaderSource -> caller, dataSourceName -> 2zm2h7a4d1dnn281ezvn|7e0ea639, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, extensions -> {}, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceSynchronousCheckins -> false, forceUseNamedDriverClass -> false, identityToken -> 2zm2h7a4d1dnn281ezvn|7e0ea639, idleConnectionTestPeriod -> 0, initialPoolSize -> 3, jdbcUrl -> jdbc:mysql://localhost:3306/test, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 15, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 3, numHelperThreads -> 3, preferredTestQuery -> null, privilegeSpawnedThreads -> false, properties -> {user=******, password=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ]
2019-07-26 23:54:33,677 INFO [com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource] - 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, contextClassLoaderSource -> caller, dataSourceName -> 2zm2h7a4d1dnn281ezvn|6e1567f1, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, extensions -> {}, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceSynchronousCheckins -> false, forceUseNamedDriverClass -> false, identityToken -> 2zm2h7a4d1dnn281ezvn|6e1567f1, idleConnectionTestPeriod -> 0, initialPoolSize -> 3, jdbcUrl -> jdbc:mysql://localhost:3306/test1, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 15, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 3, numHelperThreads -> 3, preferredTestQuery -> null, privilegeSpawnedThreads -> false, properties -> {user=******, password=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ]
2019-07-26 23:54:33,696 INFO [org.apache.shiro.session.mgt.AbstractValidatingSessionManager] - Enabling session validation scheduler...
2019-07-26 23:54:33,704 INFO [test_JdbcRealm.TestAuthencationStrategy] - 登陆成功
可以看到虽然test数据库中没有wangwu这个用户,但是test1数据库中有,所以myRealm1的认证过程是成功了的,而myRealm的认证过程毋庸置疑是失败了的,但是我们这里配的认证策略是FirstSuccessfulStrategy,所以只要有一个成功,就认证成功。
我们把认证策略改成AllSuccessfulStrategy再来测试一下上面的认证流程,发现控制台输出了如下内容:
2019-07-26 23:59:26,933 INFO [com.mchange.v2.log.MLog] - MLog clients using slf4j logging.
2019-07-26 23:59:27,323 INFO [com.mchange.v2.c3p0.C3P0Registry] - Initializing c3p0-0.9.5.2 [built 08-December-2015 22:06:04 -0800; debug? true; trace: 10]
2019-07-26 23:59:27,447 INFO [org.apache.shiro.config.IniSecurityManagerFactory] - Realms have been explicitly set on the SecurityManager instance - auto-setting of realms will not occur.
2019-07-26 23:59:27,476 INFO [com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource] - 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, contextClassLoaderSource -> caller, dataSourceName -> 2zm2h7a4d1jymk14v9ac3|7e0ea639, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, extensions -> {}, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceSynchronousCheckins -> false, forceUseNamedDriverClass -> false, identityToken -> 2zm2h7a4d1jymk14v9ac3|7e0ea639, idleConnectionTestPeriod -> 0, initialPoolSize -> 3, jdbcUrl -> jdbc:mysql://localhost:3306/test, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 15, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 3, numHelperThreads -> 3, preferredTestQuery -> null, privilegeSpawnedThreads -> false, properties -> {user=******, password=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ]
org.apache.shiro.authc.UnknownAccountException: No account found for user [wangwu]
at org.apache.shiro.realm.jdbc.JdbcRealm.doGetAuthenticationInfo(JdbcRealm.java:244)
2019-07-26 23:59:27,761 ERROR [test_JdbcRealm.TestAuthencationStrategy] - 用户名或密码错误,登陆失败
at org.apache.shiro.realm.AuthenticatingRealm.getAuthenticationInfo(AuthenticatingRealm.java:571)
at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doMultiRealmAuthentication(ModularRealmAuthenticator.java:219)
at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doAuthenticate(ModularRealmAuthenticator.java:269)
at org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:198)
at org.apache.shiro.mgt.AuthenticatingSecurityManager.authenticate(AuthenticatingSecurityManager.java:106)
at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:275)
at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:260)
at test_JdbcRealm.TestAuthencationStrategy.main(TestAuthencationStrategy.java:30)
报了用户找不到的异常,因为在test数据库中我们并没有wangwu这个用户,所以myRealm认证是失败的,而我们配置了AllSuccessfulStrategy这个策略,只要有一个认证失败,那么最终就认证失败,因此这里输出了认证失败的提示语。
以上是我今天所看的shiro认证策略的内容和应用,如果有什么纠正和补充的请在评论区留言,谢谢!
学习shiro第三天的更多相关文章
- Shiro learning - 入门学习 Shiro中的基础知识(1)
Shiro入门学习 一 .什么是Shiro? 看一下官网对于 what is Shiro ? 的解释 Apache Shiro (pronounced “shee-roh”, the Japanese ...
- 学习shiro第二天
昨天讲了shiro的认证流程以及代码实现,今天将对这个进行扩展. 因为我们的测试数据是shiro.ini文件中配置的静态数据,但实际上数据应该从数据库中查询出来才合理,因此我们今天讲讲JdbcReal ...
- 我的MYSQL学习心得(三) 查看字段长度
我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...
- PyQt4入门学习笔记(三)
# PyQt4入门学习笔记(三) PyQt4内的布局 布局方式是我们控制我们的GUI页面内各个控件的排放位置的.我们可以通过两种基本方式来控制: 1.绝对位置 2.layout类 绝对位置 这种方式要 ...
- 学习javascript数据结构(三)——集合
前言 总括: 本文讲解了数据结构中的[集合]概念,并使用javascript实现了集合. 原文博客地址:学习javascript数据结构(三)--集合 知乎专栏&&简书专题:前端进击者 ...
- 小菜学习设计模式(三)—工厂方法(Factory Method)模式
前言 设计模式目录: 小菜学习设计模式(一)—模板方法(Template)模式 小菜学习设计模式(二)—单例(Singleton)模式 小菜学习设计模式(三)—工厂方法(Factory Method) ...
- MATLAB地图工具箱学习总结(三)地图工具箱的基本知识
MATLAB地图工具箱学习总结(三)地图工具箱的基本知识 今天想要介绍的是一些比较基础的函数.了解了这些函数,地图投影的基本概念才能真正明白.而要想继续研究MATLAB中有关地图投影的函数,尤其是未来 ...
- python学习心得第三章
python学习心得第三章 1.三元运算 变量=值1 if 条件 else 值2 由图如果条件成立则赋值1给变量,如果条件不成立则赋值2给变量. 2.数据类型 集合:set() class set(o ...
- C#可扩展编程之MEF学习笔记(三):导出类的方法和属性
前面说完了导入和导出的几种方法,如果大家细心的话会注意到前面我们导出的都是类,那么方法和属性能不能导出呢???答案是肯定的,下面就来说下MEF是如何导出方法和属性的. 还是前面的代码,第二篇中已经提供 ...
随机推荐
- LFI (local file inclusion vulnerability)本地文件包含
代码实例: <?php $file = $_GET['file']; if(isset($file)) { include("pages/$file"); } else { ...
- 在Dynamis CRM中打造一键保存关闭刷新案例的功能
关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复172或者20151114可方便获取本文,同时可以在第一时间得到我发布的最新的博文信息,follow me! 我们知道在Dynamics CR ...
- SQL学习_SELECT
查询列: SQL:SELECT name FROM heros 多列查询: SQL:SELECT name, hp_max, mp_max, attack_max, defense_max FROM ...
- 22.Java基础_StringBuilder类
String类对象的拼接操作:执行到s+="world"语句时,常量池会先创建"world"对象,再去创建"helloworld"对象,最后 ...
- 爬虫 crawlSpider 分布式 增量式 提高效率
crawlSpider 作用:为了方便提取页面整个链接url,不必使用创参寻找url,通过拉链提取器,将start_urls的全部符合规则的URL地址全部取出 使用:创建文件scrapy startp ...
- 深浅拷贝及 join set
1.join s="**".join (['风清扬',"独孤求败"] ) join 把里面的东西拿出来,进行拼接 s="_". ...
- 3.git 远程
首次拉取代码的话.可以使用 git clone 这个指令 git clone https://github.com/guohongze/adminset.git 带密码方式 git clone htt ...
- Jenkins如何集成运行testng.xml文件的解决方案
前言: 在我们使用maven+testng+restassured+reportng实现接口测试框架时,会发现在本机创建项目,进行一些pom引用和简单的封装后,很快就可以直接利用idea自带的test ...
- Ubuntu下的录GIF神器——Peek
最近一直在找Ubuntu下面录GIF好用方便的软件一直没找到,很多都是要获取录屏四角的坐标,现在终于找到了,就是我们的录GIF神器——Peek. 1 获取Peek的ppa源 sudo add-apt- ...
- Python socket & socket server
socket 网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket(套接字). 建立网络通信连接至少要一对socket.socket是对TCP/IP的封装 使用方法 ...