第四章:Shiro的身份认证(Authentication)
Authentication概述
Authentication 是指身份验证的过程——即证明一个用户实际上是不是他们所说的他们是谁。也就是说通过提交用户的身份和凭证给Shiro,以判断它们是否和应用程序预期的相匹配。
1:Principals(身份):是Subject 的‘identifying attributes(标识属性)’。比如我们登录提交的用户名。
2:Credentials(凭证):通常是只被Subject 知道的秘密值,它用来作为一种起支持作用的证据,此证据事实上包含着所谓的身份证明。比如我们登录提供的密码
1. 收集Subjects 提交的Principals(身份)和Credentials(凭证);
2. 提交Principals(身份)和Credentials(凭证)进行身份验证;
3. 如果提交成功,则允许访问,否则重新进行身份验证或者阻止访问。
认证样例
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
token.setRememberMe(true);
样例使用UsernamePasswordToken 来支持最常见的用户名/密码的身份验证方法。这是Shiro的org.apache.shiro.authc.AuthenticationToken 的接口,是Shiro 代表提交的Principals(身份)和Credentials(凭证)的身份验证系统所使用的基本接口的一个实现。
Subject currentUser = SecurityUtils.getSubject();
currentUser.login(token);
如果认证成功,会没有返回,也没有例外,通过。
如果认证失败,会拋出例外,你可以在程序中捕获并处理,如下示例:
try {
currentUser.login(token);
} catch ( UnknownAccountException uae ) { …
} catch ( IncorrectCredentialsException ice ) { …
} catch (LockedAccountException lae ) { …
} catch (ExcessiveAttemptsException eae ) { …
} … catch your own …
currentUser.logout();
当你调用logout,任何现有的Session 都将会失效,而且任何身份都将会失去关联(例如,在Web 应用程序中,RememberMe cookie 也将被删除)。在Subject 注销后,该Subject的实例被再次认为是匿名的,当然,除了Web 应用程序。
注意:由于在Web 应用程序记住身份往往是依靠Cookies,然而Cookies 只能在Response 被committed 之前被删除,所以强烈建议在调用subject.logout()后立即将终端用户重定向到一个新的视图或页面。
这样能够保证任何与安全相关的Cookies 都能像预期的一样被删除。这是HTTP cookies 的功能限制,而不是Shiro的。
Remembered和Authenticated
一个记住我的Subject 不是匿名的,是有一个已知的身份ID(也就是subject.getPrincipals()是非空的)。但是这个被记住的身份ID 是在之前的session 中被认证的。如果subject.isRemembered()返回true,则Subject 被认为是被记住的。
一个已认证的Subject 是指在当前Session 中被成功地验证过了(也就是说,login方法被调用并且没有抛出异常)。如果subject.isAuthenticated()返回true 则认为Subject 已通过验证。
Remembered 和Authenticated 是互斥的——若其中一个为真则另一个为假,反之亦然
认证顺序
public class MyRealm extends AuthorizingRealm{
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String userName = (String) getAvailablePrincipal(principals);
//通过用户名去获得用户的所有资源,并把资源存入info中
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
Set<String> s = new HashSet<String>();
s.add("p1"); s.add("p2"); info.setStringPermissions(s);
Set<String> r = new HashSet<String>();
r.add("r1"); r.add("r2"); info.setRoles(r);
return info;}
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) throws AuthenticationException {
//token中储存着输入的用户名和密码
UsernamePasswordToken upToken = (UsernamePasswordToken)token;
String username = upToken.getUsername();
String password = String.valueOf(upToken.getPassword());
//通常是与数据库中用户名和密码进行比对,这里就省略了
//比对成功则返回info,比对失败则抛出对应信息的异常AuthenticationException
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, password .toCharArray(),getName());
return info; }}
配置多个Realm
if(username.equals("javass")){
throw new AuthenticationException("MyRealm2 认证失败");
}
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, password .toCharArray(),getName());
myRealm1=cn.javass.hello.MyRealm
myRealm2=cn.javass.hello.MyRealm2
由于有多个realm,一般就需要配置AuthenticationStrategy了,而AuthenticationStrategy是跟Authenticator(认证器)相关的。
authenticator = org.apache.shiro.authc.pam.ModularRealmAuthenticator
authcStrategy = org.apache.shiro.authc.pam.AllSuccessfulStrategy
authenticator.authenticationStrategy = $authcStrategy
authenticator.realms=$myRealm2,$myRealm1
securityManager.authenticator = $authenticator
AtLeastOneSuccessfulStrategy :如果一个(或更多)Realm 验证成功,则整体的尝试被认为是成功的。如果没有一个验证成功,则整体尝试失败。
FirstSuccessfulStrategy 只有第一个成功地验证的Realm 返回的信息将被使用。所有进一步的Realm 将被忽略。如果没有一个验证成功,则整体尝试失败
AllSucessfulStrategy 为了整体的尝试成功,所有配置的Realm 必须验证成功。如果没有一个验证成功,则整体尝试失败。
ModularRealmAuthenticator 默认的是AtLeastOneSuccessfulStrategy
public class MyAuthenticationStrategy extends AbstractAuthenticationStrategy{
public AuthenticationInfo afterAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo singleRealmInfo, AuthenticationInfo aggregateInfo, Throwable t) throws AuthenticationException {
if(realm.getName().equals("myRealm2")){
if(singleRealmInfo==null || singleRealmInfo.getPrincipals()==null){
throw new AuthenticationException("主战认证未通过");
}
}
return super.afterAttempt(realm, token, singleRealmInfo, aggregateInfo, t);
}
}
至于具体覆盖扩展什么方法,需要根据你具体的策略来定。
多个Realm的验证顺序
非常重要的一点是:ModularRealmAuthenticator 将与Realm 实例以迭代的顺序进行交互。
在SecurityManager 中已经配置好了ModularRealmAuthenticator 对Realm实例的访问。当执行一个认证尝试时,它将会遍历该集合,并对每一个支持提交AuthenticationToken 的Realm 调用Realm 的getAuthenticationInfo 方法
当你配置多个realm的时候,处理的顺序默认就是你配置的顺序。
这种情况通常就是只定义了realm,而没有配置securityManager的realms
也就是显示的配置securityManager.realms,那么执行的顺序就是你配置该值的realm的顺序。
通常更推荐显示排列。
第四章:Shiro的身份认证(Authentication)相关推荐
- Shiro(三) 身份认证源码分析与 MD5 盐值加密
文章目录 1. 身份认证 2. 身份验证的基本流程 3. 身份验证实现 3.1 在 `login.jsp` 添加登录表单 3.2 添加表单提交的 Controller 3.3 完善 Realm 的身份 ...
- SpringBoot学习:整合shiro(身份认证和权限认证),使用EhCache缓存
一.在pom中引入依赖jar包 1 <properties> 2 <shiro.version>1.3.2</shiro.version> 3 </prope ...
- Spring Security身份认证Authentication
文章目录 Authentication(身份认证框架)的架构 SecurityContextHolder AuthenticationManager AbstractAuthenticationPro ...
- Spring Boot Shiro视频 - 身份认证准备工作
[视频 & 交流平台] à SpringBoot视频 http://study.163.com/course/introduction.htm?courseId=1004329008& ...
- shiro 方法级别细粒度权限控制_第四章:Shiro的身份认证(Authentication)——深入浅出学Shiro细粒度权限开发框架——私塾在线原创...
nStep3:SubjectManager 接收token 以及简单地委托给内部的Authenticator 实例通过调用authenticator.authenticate(token).这通常是一 ...
- db2 c语言,DB2数据库安全(二)——身份认证
根据<循序渐进DB2>(牛新庄)第13章内容整理 身份认证(authentication) 1.什么时候进行身份认证 DB2身份认证 控制数据库安全性策略的以下方面:谁有权访问实例或数据库 ...
- mysql url认证_Springboot+shiro基于url身份认证和授权认证
你还不会shiro吗?前奏 shiro核心配置文件(rolesFilter可选). 身份认证 多表登录源如何操作? 授权管理 如何解决界面多角色/资源问题 访问效果 权限管理在日常开发中很重要,所以硬 ...
- Shiro身份认证授权原理
shiro在应用程序中的使用是用Subject为入口的, 最终subject委托给真正的管理者ShiroSecurityMannager Realm是Shiro获得身份认证信息和来源信息的地方(所以这 ...
- Springboot学习笔记(四)SpringSecurity.Shiro
前言: 学习B站UP主狂神说视频笔记整理视频链接 SpringSecurity 安全简介 Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架.它实际上是保护基于sprin ...
最新文章
- javascript基础学习(六)
- golang中的strings.ContainsRune
- C++和Java中类继承同名函数的区分
- Linux学习之系统编程篇:孤儿进程和僵尸进程(描述对象都是子进程)
- java 入侵 mysql_Java访问数据库Mysql
- 技术选型:Sentinel vs Hystrix
- 24口光纤配线架 cad块_光纤配线架cad画法
- 打印异常堆栈_关于日志打印行号的性能案例
- 如何在jsp页面中连接mysql数据库_如何使用JSP访问MySQL数据库
- 2017.9.22 middle 失败总结
- java常规普氏分析法_人脸对齐:Procrustes analysis 普氏分析
- linux python3 装pip,linux 安装pip 和python3(示例代码)
- python离线语音识别_python语音识别模块
- JasperReport导出Excel锁定行或列
- 截取邮箱后缀名,拼接访问邮箱地址
- 【科研】浅学Cross-attention?
- 别踩白块_前端H5游戏毕设
- FPGA错误集锦(二):Output pins are stuck at VCC or GND
- 基于微信运动场地预约小程序 毕业设计毕业论文 开题报告和效果图(基于微信小程序毕业设计题目选题课题)
- 重庆理工大学计算机学院学概率论,重庆理工大学概率论与数理统计参考附标准答案(a)...