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目录贴 身份验证,即在应用中谁能证明他就是他本人.一般提供如他 ...
随机推荐
- Linux电源管理【转】
转自:http://www.cnblogs.com/sky-zhang/archive/2012/06/05/2536807.html PM notifier机制: 应用场景: There are s ...
- jrockit静默安装笔记
操作系统安装版本:CentOS-6.4-i386-minimal JDK安装版本:jrockit-jdk1.6.0_20-R28.1.0-4.0.1-linux-ia32 1.通过SecureFX工具 ...
- CSS高度塌陷问题解决方案
高度塌陷的存在:原因分析 1 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /& ...
- lvs持久连接及防火墙标记实现多端口绑定服务
lvs持久连接及防火墙标记实现多端口绑定服务 LVS持久连接: PCC:将来自于同一个客户端发往VIP的所有请求统统定向至同一个RS: PPC:将来自于一个客户端发往某VIP的某端口的所有请求统统定向 ...
- ios 侧边手势滑动返回 禁用/开启 功能
// 禁用 返回手势 if ([self.navigationController respondsToSelector:@selector(interactivePopGestureR ...
- Linear Algebra(未完待续)
[矩阵消元] The result of multiplying a matrix by some vector is a combination of the columns of the matr ...
- Iterator 接口
首先要从foreach说起,我们都知道对象,数组和对象可以被foreach语法遍历,数字和字符串却不行.其实除了数组和对象之外PHP内部还提供了一个 Iterator 接口,实现了Iterator接口 ...
- 【C++ Primer | 19】控制内存分配
重载new和delete 1. 测试代码: #include<iostream> #include<new> using namespace std; class A { pu ...
- Promise 基础学习
Promise 是ES6的特性之一,采用的是 Promise/A++ 规范,它抽象了异步处理的模式,是一个在JavaScript中实现异步执行的对象. 按照字面释意 Promise 具有"承 ...
- POJ 2718【permutation】
POJ 2718 问题描述: 给一串数,求划分后一个子集以某种排列构成一个数,余下数以某种排列构成另一个数,求这两个数最小的差,注意0开头的处理. 超时问题:一开始是得到一个数列的组合之后再从中间进行 ...