(四)自定义多个Realm以及Authenticator与AuthenticationStrategy
多Realm配置
#声明一个realm
myRealm1=com.github.zhangkaitao.shiro.chapter2.realm.MyRealm1
myRealm2=com.github.zhangkaitao.shiro.chapter2.realm.MyRealm2
#指定securityManager的realms实现
securityManager.realms=$myRealm1,$myRealm2
- securityManager会按照realms指定的顺序进行身份认证。此处我们使用显示指定顺序的方式指定了Realm的顺序,如果删除“securityManager.realms=$myRealm1,$myRealm2”,那么securityManager会按照realm声明的顺序进行使用(即无需设置realms属性,其会自动发现),当我们显示指定realm后,其他没有指定realm将被忽略,如“securityManager.realms=$myRealm1”,那么myRealm2不会被自动设置进去
1、变量名=全限定类名会自动创建一个类实例
2、变量名.属性=值 自动调用相应的setter方法进行赋值
3、$变量名 引用之前的一个对象实例
Authenticator及AuthenticationStrategy
- Authenticator的职责是验证用户帐号,是Shiro API中身份验证核心的入口点:
public AuthenticationInfo authenticate(AuthenticationToken authenticationToken)
throws AuthenticationException;
- SecurityManager接口继承了Authenticator,另外还有一个ModularRealmAuthenticator实现(ModularRealmAuthenticator默认使用AtLeastOneSuccessfulStrategy策略。),其委托给多个Realm进行验证,验证规则通过AuthenticationStrategy接口指定,默认提供的实现:
- FirstSuccessfulStrategy:只要有一个Realm验证成功即可,只返回第一个Realm身份验证成功的认证信息,其他的忽略;
- AtLeastOneSuccessfulStrategy:只要有一个Realm验证成功即可,和FirstSuccessfulStrategy不同,返回所有Realm身份验证成功的认证信息;
- AllSuccessfulStrategy:所有Realm验证成功才算成功,且返回所有Realm身份验证成功的认证信息,如果有一个失败就失败了。
一、案例
- 需求:
假设我们有三个realm:
myRealm1: 用户名/密码为zhang/123时成功,且返回身份/凭据为zhang/123;
myRealm2: 用户名/密码为wang/123时成功,且返回身份/凭据为wang/123;
myRealm3: 用户名/密码为zhang/123时成功,且返回身份/凭据为zhang@163.com/123,和myRealm1不同的是返回时的身份变了;
- pom.xml依赖省略,可查看前几章
- 配置shiro.ini文件
[main]
#指定securityManager的authenticator实现
authenticator=org.apache.shiro.authc.pam.ModularRealmAuthenticator
securityManager.authenticator=$authenticator #指定securityManager.authenticator的authenticationStrategy
allSuccessfulStrategy=org.apache.shiro.authc.pam.FirstSuccessfulStrategy
securityManager.authenticator.authenticationStrategy=$allSuccessfulStrategy
myRealm1=realms.MyRealm1
myRealm2=realms.MyRealm2
myRealm3=realms.MyRealm3
securityManager.realms=$myRealm1,$myRealm2,$myRealm3 [users]
zhang=123
wang=123
- 认证策略为FirstSuccessfulStrategy ,只要有一个Realm验证成功即可,只返回第一个Realm身份验证成功的认证信息,其他的忽略
- MyRealm1.java
package realms; import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.SimpleAccount;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection; public class MyRealm1 extends AuthorizingRealm{ /**
* 判断授权的
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// TODO Auto-generated method stub
return null;
} /**
* 判断认证的
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String userName=token.getPrincipal().toString();
String passWord=new String((char[])token.getCredentials()); if(!userName.equals("zhang")) throw new UnknownAccountException("Realm1 用户名错误");
if(!passWord.equals("123")) throw new IncorrectCredentialsException("Realm1 密码错误"); return new SimpleAccount(userName, passWord, getName());
} }
- MyRealm2.java
package realms; import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.SimpleAccount;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection; public class MyRealm2 extends AuthorizingRealm{
/**
* 判断授权的
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// TODO Auto-generated method stub
return null;
} /**
* 判断认证的
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String userName=token.getPrincipal().toString();
String passWord=new String((char[])token.getCredentials()); if(!userName.equals("wang")) throw new UnknownAccountException("Realm2 用户名错误");
if(!passWord.equals("123")) throw new IncorrectCredentialsException("Realm2 密码错误"); return new SimpleAccount(userName, passWord, getName());
} }
- MyRealm3.java
package realms; import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.SimpleAccount;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection; public class MyRealm3 extends AuthorizingRealm{
/**
* 判断授权的
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// TODO Auto-generated method stub
return null;
} /**
* 判断认证的
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String userName=token.getPrincipal().toString();
String passWord=new String((char[])token.getCredentials()); if(!userName.equals("zhang")) throw new UnknownAccountException("Realm3 用户名错误");
if(!passWord.equals("123")) throw new IncorrectCredentialsException("Realm4 密码错误"); return new SimpleAccount("zhang@163.com", passWord, getName());
} }
- 测试
package test; import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject; public class TestMain {
public static void main(String[] args) {
SecurityManager securityManager=new IniSecurityManagerFactory("classpath:shiro.ini").getInstance();
SecurityUtils.setSecurityManager(securityManager); Subject subject=SecurityUtils.getSubject(); AuthenticationToken token=new UsernamePasswordToken("zhang","123");
try {
subject.login(token);
PrincipalCollection ps=subject.getPrincipals();
System.out.println(ps.asList()); System.out.println(ps.getRealmNames());
System.out.println(subject.getPrincipal().toString()); } catch (UnknownAccountException e) {
System.out.println(e.getMessage());
}catch(IncorrectCredentialsException e){
System.out.println(e.getMessage());
} }
}
- 结果:
因为是FirstSuccessfulStrategy策略,myRealm1认证成功,所以只返回这个Realm的认证信息,其他的省略。
- 修改shiro.ini,认证策略修改为AtLeastOneSuccessfulStrategy ,其他文件均不变
[main]
authenticator=org.apache.shiro.authc.pam.ModularRealmAuthenticator
securityManager.authenticator=$authenticator
atLeastOneSuccessfulStrategy=org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy
securityManager.authenticator.authenticationStrategy=$atLeastOneSuccessfulStrategy
myRealm1=realms.MyRealm1
myRealm2=realms.MyRealm2
myRealm3=realms.MyRealm3
securityManager.realms=$myRealm1,$myRealm2,$myRealm3 [users]
zhang=123
wang=123

- 修改shiro.ini,认证策略修改为AllSuccessfulStrategy,其他文件均不变
[main]
authenticator=org.apache.shiro.authc.pam.ModularRealmAuthenticator
securityManager.authenticator=$authenticator
atLeastOneSuccessfulStrategy=org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy
securityManager.authenticator.authenticationStrategy=$atLeastOneSuccessfulStrategy
myRealm1=realms.MyRealm1
myRealm2=realms.MyRealm2
myRealm3=realms.MyRealm3
securityManager.realms=$myRealm1,$myRealm2,$myRealm3 [users]
zhang=123
wang=123

(四)自定义多个Realm以及Authenticator与AuthenticationStrategy的更多相关文章
- spring boot / cloud (四) 自定义线程池以及异步处理@Async
spring boot / cloud (四) 自定义线程池以及异步处理@Async 前言 什么是线程池? 线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务.线 ...
- Authenticator及AuthenticationStrategy
Authenticator的职责是验证用户帐号,是Shiro API中身份验证核心的入口点: 如果验证成功,将返回AuthenticationInfo 验证信息:此信息中包含了身份及凭证:如果验证失败 ...
- Shiro笔记(四)Shiro的realm认证
认证流程: 1.获取当前Subject.调用SecurityUtils.getSubject(); 2.测试当前用户是否已经被认证,即是否已经登录,调用Subject的isAurhenticated( ...
- 自定义shiro的Realm实现和CredentialsMatcher实现以及Token实现
Realm是shiro比较核心的接口,简单说它的实现类就是校验用户输入的账号信息的地方.如果想自定义实现一般的配置文件如下: <!--自定义Realm 继承自AuthorizingRealm - ...
- 项目一:第十四天 1.在realm中动态授权 2.Shiro整合ehcache 缓存realm中授权信息 3.动态展示菜单数据 4.Quartz定时任务调度框架—Spring整合javamail发送邮件 5.基于poi实现分区导出
1 Shiro整合ehCache缓存授权信息 当需要进行权限校验时候:四种方式url拦截.注解.页面标签.代码级别,当需要验证权限会调用realm中的授权方法 Shiro框架内部整合好缓存管理器, ...
- 走进AngularJs(四)自定义指令----(中)
上一篇简单介绍了自定义一个指令的几个简单参数,restrict.template.templateUrl.replace.transclude,这几个理解起来相对容易很多,因为它们只涉及到了表现,而没 ...
- VSTO学习(四)——自定义Excel UI 转载
本专题概要 引言 自定义任务窗体(Task Pane) 自定义选项卡,即Ribbon 自定义上下文菜单 小结 引言 在上一个专题中为大家介绍如何创建Excel的解决方案,相信大家通过从上面一个专题之后 ...
- Shiro - 自定义filterChainDefinitions和Realm
在Spring Context中定义shiroFilter(org.apache.shiro.spring.web.ShiroFilterFactoryBean)时需要为其filterChainDef ...
- AngularJS学习笔记(四) 自定义指令
指令(directive)是啥?简单来说就是实现一定功能的XXX...之前一直用的ng-model,ng-click等等都是指令.当我有一个ng没提供的需求的时候,就可以自定义个指令.指令的好处显而易 ...
随机推荐
- httpPostedFile实现WEBAPI文件上传
public void PostUpload() { var httpPostedFile = HttpContext.Current.Request.Files; foreach(string p ...
- 微信小程序 位置定位position详解,相对定位relative,绝对定位absolute相关问题
一.位置position[定位属性:static,relative,absolute,fixed,inherit,-ms-page,initial,unset] 1.static:元素框正常生成,块级 ...
- 使用ConstraintLayout(约束布局)构建响应式UI
使用ConstraintLayout(约束布局)构建响应式UI 转 https://www.300168.com/yidong/show-2740.html 核心提示:ConstraintLa ...
- 阶段5 3.微服务项目【学成在线】_day09 课程预览 Eureka Feign_09-课程详情页面静态化-静态页面测试
4 课程详情页面静态化 4.1 静态页面测试 4.1.1 页面内容组成 我们在编写一个页面时需要知道哪些信息是静态信息,哪些信息为动态信息,下图是页面的设计图: 打开静态页面,观察每部分的内容. 红色 ...
- 阶段5 3.微服务项目【学成在线】_day18 用户授权_15-细粒度授权-我的课程细粒度授权-实现
先定义接口 实现接口 service 需要通过conpanyId去查询课程的列表 定义dao 要查课程的图片 名称 等相关信息.所以使用Mybatis来实现 定义Mapper 看这个dao里面方法在哪 ...
- git 关于Git每次进入都需要输入用户名和密码的问题解决
解决办法: git bash进入你的项目目录,输入: git config --global credential.helper store 然后你会在你本地生成一个文本,上边记录你的账号和密码.当然 ...
- (十七)super关键字(转)
--本文摘自孤傲苍狼博客. 一.super关键字
- 【Leetcode_easy】733. Flood Fill
problem 733. Flood Fill 题意:图像处理中的泛洪填充算法,常见的有四邻域像素填充法.八邻域像素填充法.基于扫描线的像素填充法,实现方法分为递归与非递归(基于栈). 泛洪填充算法原 ...
- nfs搭建;nfs监控;mount对于nfs的相应配置
nfs搭建 https://www.cnblogs.com/lms0755/p/9211585.html https://www.jianshu.com/p/e47cccbb3ae5 https:// ...
- 阿里云ecs自动创建快照教程
最近在一个博客联盟的微信群里面看到经常有朋友问阿里云的ecs服务器怎么设置自动创建快照,也不知道最近是怎么了,看到问这个问题的朋友有有四五个左右了,今天就特意到博客里来费大家分享设置自动创建快照的方法 ...