Shiro笔记(二)身份验证
Shiro笔记(二)身份验证
一、核心代码
@Test
public void helloWorldTest(){
IniSecurityManagerFactory factory =
new IniSecurityManagerFactory("classpath:shiro-jdbc-realm.ini");
SecurityManager manager = factory.getInstance();
//全局设置,一次即可
SecurityUtils.setSecurityManager(manager);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token =
new UsernamePasswordToken("Peter", "123");
try{
subject.login(token);
}catch (AuthenticationException e){
e.printStackTrace();
} Assert.assertEquals(true,subject.isAuthenticated());
//退出登录
subject.logout();
shiro.ini文件:
[users]
Peter=
Tom=
二、身份认证流程:

Authenticator 可能会委托给相应的 AuthenticationStrategy 进行多 Realm 身份验证,默认
ModularRealmAuthenticator 会调用 AuthenticationStrategy 进行多 Realm 身份验证;
Authenticator 会把相应的 token 传入 Realm,从 Realm 获取身份验证信息
三、Realm
Shiro 从从 Realm 获取安全数据(如用户、角色、权限)
Reaml接口:
public interface Realm {
//获得唯一的名字
String getName();
//判断此realm是否支持此token
boolean supports(AuthenticationToken token);
//获取token认证信息
AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException;
}
一)单Realm配置
public class MyRealm implements Realm{
public String getName() {
return "myRealm";
}
public boolean supports(AuthenticationToken authenticationToken) {
//仅支持UsernamePasswordToken类型
return authenticationToken instanceof UsernamePasswordToken;
}
public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//获取用户名
String username= (String) token.getPrincipal();
//获取密码
String password=new String((char[]) token.getCredentials());
if(!"Peter".equals(username)){
throw new UnknownAccountException();
}
if(!"123".equals(password)){
throw new IncorrectCredentialsException();
}
return new SimpleAuthenticationInfo(username,password,getName());
}
}
ini文件指定:
myRealm=com.tang.shirotest.LoginLogoutTest
securityManager.realms=$myRealm
二)JDBC Realm的使用
[main]
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
dataSource=com.alibaba.druid.pool.DruidDataSource
dataSource.driverClassName=com.mysql.jdbc.Driver
dataSource.url=jdbc:mysql://localhost:3306/shiro
dataSource.username=root
dataSource.password=jiapi1990
jdbcRealm.dataSource=$dataSource
securityManager.realms=$jdbcRealm
三)Authenticator及AuthenticationStrategy
Authenticator的职责是验证用户账号,接口为:
public interface Authenticator {
AuthenticationInfo authenticate(AuthenticationToken var1) throws AuthenticationException;
}
SecurityManager 接口继承了 Authenticator,另外还有一个 ModularRealmAuthenticator 实现,
其委托给多个 Realm 进行验证,验证规则通过 AuthenticationStrategy 接口指定,默认提供
的实现:
FirstSuccessfulStrategy:只要有一个 Realm 验证成功即可,只返回第一个 Realm 身份验证
成功的认证信息,其他的忽略;
AtLeastOneSuccessfulStrategy:只要有一个 Realm 验证成功即可,和 FirstSuccessfulStrategy
不同,返回所有 Realm 身份验证成功的认证信息;
AllSuccessfulStrategy:所有 Realm 验证成功才算成功,且返回所有 Realm 身份验证成功的
认证信息,如果有一个失败就失败了
ModularRealmAuthenticator 默认使用 AtLeastOneSuccessfulStrategy 策略。
ini文件:
#指定 securityManager 的 authenticator 实现
authenticator=org.apache.shiro.authc.pam.ModularRealmAuthenticator
securityManager.authenticator=$authenticator
#指定 securityManager.authenticator 的 authenticationStrategy
allSuccessfulStrategy=org.apache.shiro.authc.pam.AllSuccessfulStrategy
securityManager.authenticator.authenticationStrategy=$allSuccessfulStrategy
myRealm1=com.github.zhangkaitao.shiro.chapter2.realm.MyRealm1
myRealm2=com.github.zhangkaitao.shiro.chapter2.realm.MyRealm2
myRealm3=com.github.zhangkaitao.shiro.chapter2.realm.MyRealm3
securityManager.realms=$myRealm1,$myRealm3
AuthenticationStrategy接口:
public interface AuthenticationStrategy {
//在所有 Realm 验证之前调用
AuthenticationInfo beforeAllAttempts(Collection<? extends Realm> realms, AuthenticationToken token) throws AuthenticationException;
//在每个 Realm 之前调用
AuthenticationInfo beforeAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo aggregate) throws AuthenticationException;
//在每个 Realm 之后调用
AuthenticationInfo afterAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo singleRealmInfo, AuthenticationInfo aggregateInfo, Throwable t)
throws AuthenticationException;
////在所有 Realm 之后调用
AuthenticationInfo afterAllAttempts(AuthenticationToken token, AuthenticationInfo aggregate) throws AuthenticationException;
}
自定义实现:
public class AtLeastTwoAuthenticatorStrategy extends AbstractAuthenticationStrategy {
@Override
public AuthenticationInfo beforeAllAttempts(Collection<? extends Realm> realms, AuthenticationToken token) throws AuthenticationException {
return new SimpleAuthenticationInfo();//返回一个权限的认证信息
}
@Override
public AuthenticationInfo beforeAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo aggregate) throws AuthenticationException {
return aggregate;//返回之前合并的
}
@Override
public AuthenticationInfo afterAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo singleRealmInfo, AuthenticationInfo aggregateInfo, Throwable t) throws AuthenticationException {
AuthenticationInfo info;
if (singleRealmInfo == null) {
info = aggregateInfo;
} else {
if (aggregateInfo == null) {
info = singleRealmInfo;
} else {
info = merge(singleRealmInfo, aggregateInfo);
}
}
return info;
}
@Override
public AuthenticationInfo afterAllAttempts(AuthenticationToken token, AuthenticationInfo aggregate) throws AuthenticationException {
if (aggregate == null || CollectionUtils.isEmpty(aggregate.getPrincipals()) || aggregate.getPrincipals().getRealmNames().size() < 2) {
throw new AuthenticationException("Authentication token of type [" + token.getClass() + "] " +
"could not be authenticated by any configured realms. Please ensure that at least two realm can " +
"authenticate these tokens.");
}
return aggregate;
}
}
Shiro笔记(二)身份验证的更多相关文章
- Shiro学习之身份验证
身份验证,即在应用中谁能证明他就是他本人.一般提供如他们的身份ID一些标识信息来表明他就是他本人,如提供身份证,用户名/密码来证明. 在shiro中,用户需要提供principals (身份)和cre ...
- Shiro:学习笔记(1)——身份验证
Shiro——学习笔记(1) 1.核心概念 1.Shiro不会自己去维护用户.维护权限:这些需要我们自己去设计/提供:然后通过相应的接口注入给Shiro.2.应用代码直接交互的对象是Subject,也 ...
- 【二】shiro入门 之 身份验证
大体步骤如下: 1.首先通过new IniSecurityManagerFactory 并指定一个ini 配置文件来创建一个SecurityManager工厂: 2.接着获取SecurityManag ...
- Shiro -- (二) 身份验证基本流程
简介: 在 shiro 中,用户需要提供 principals (身份)和 credentials(证明)给 shiro,从而应用能验证用户身份: principals:身份,即主体的标识属性,可以是 ...
- shiro 简单的身份验证 案例
Apache Shiro是Java的一个安全框架,Shiro可以帮助我们完成:认证.授权.加密.会话管理.与Web集成.缓存等. 简单的身份验证 项目目录: 首先,在shiro.ini里配置了用户名和 ...
- shiro系列二、身份验证和授权
一.身份验证 先来看看身份验证的流程 流程如下: 1.首先调用Subject.login(token)进行登录,其会自动委托给Security Manager,调用之前必须通过SecurityUtil ...
- 跟开涛老师学shiro -- 身份验证
身份验证,即在应用中谁能证明他就是他本人.一般提供如他们的身份ID一些标识信息来表明他就是他本人,如提供身份证,用户名/密码来证明. 在shiro中,用户需要提供principals (身份)和cre ...
- 第二章:shiro身份验证
身份验证,即在应用中谁能证明他就是他本人.一般提供如他们的身份ID一些标识信息来表明他就是他本人,如提供身份证,用户名/密码来证明. 在shiro中,用户需要提供principals (身份)和cre ...
- shiro身份验证
身份验证,即在应用中谁能证明他就是他本人.一般提供如他们的身份ID一些标识信息来表明他就是他本人,如提供身份证,用户名/密码来证明. 在shiro中,用户需要提供principals (身份)和cre ...
- 第二章 身份验证——《跟我学Shiro》
转发:https://www.iteye.com/blog/jinnianshilongnian-2019547 目录贴:跟我学Shiro目录贴 身份验证,即在应用中谁能证明他就是他本人.一般提供如他 ...
随机推荐
- Faster rcnn代码理解(1)
这段时间看了不少论文,回头看看,感觉还是有必要将Faster rcnn的源码理解一下,毕竟后来很多方法都和它有相近之处,同时理解该框架也有助于以后自己修改和编写自己的框架.好的开始吧- 这里我们跟着F ...
- 一个有趣的小例子,带你入门协程模块-asyncio
一个有趣的小例子,带你入门协程模块-asyncio 上篇文章写了关于yield from的用法,简单的了解异步模式,[https://www.cnblogs.com/c-x-a/p/10106031. ...
- TYpeScript接口的使用
1.接口中的属性值的使用: // 作用是强制类型检查 interface Iperson { name: string; age: string; } class Person { construct ...
- matplotlib画堆叠条形图
import matplotlib.pyplot as plt%matplotlib inlineplt.style.use('ggplot') plt.style.use("ggplot& ...
- WAP网页中点击链接直接拨打电话的方法
主要方法有两种: 第一种: 这种也是最简单的. 示例代码: <a href="tel:+18790853577">点击拨打</a> 第二种: <a h ...
- python 全栈开发,Day55(jQuery的位置信息,JS的事件流的概念(重点),事件对象,jQuery的事件绑定和解绑,事件委托(事件代理))
一.jQuery的位置信息 jQuery的位置信息跟JS的client系列.offset系列.scroll系列封装好的一些简便api. 一.宽度和高度 获取宽度 .width() 描述:为匹配的元素集 ...
- 基于 OSGi 的面向服务的组件编程,helloworld
基于 OSGi 的面向服务的组件编程 OSGi(Open Services Gateway Initiative,开放服务网关协议)提供了一个面向服务组件的编程模型,基于 OSGi 编程,具有模块化, ...
- RabbitMQ(一):RabbitMQ 安装与配置(Mac)
一.rabbitmq 安装与配置 安装: brew install rabbitmq # 进入安装目录 cd /usr/local/Cellar/rabbitmq/3.7.12 # 启动 brew s ...
- 使用 Nuget安装DLL
使用Nuget安装Mysql https://www.nuget.org/packages/MySql.Data 安装NewtonJson https://www.nuget.org/packages ...
- Kibana加载样本数据
kibana 6.2 加载样本数据 kibana loading sample data 下载样本数据 # 莎士比亚经典作品 wget https://download.elastic.co/demo ...