• Realm配置

    #声明一个realm
myRealm1=com.github.zhangkaitao.shiro.chapter2.realm.MyRealm1
myRealm2=com.github.zhangkaitao.shiro.chapter2.realm.MyRealm2
#指定securityManager的realms实现
securityManager.realms=$myRealm1,$myRealm2
  1. securityManager会按照realms指定的顺序进行身份认证。此处我们使用显示指定顺序的方式指定了Realm的顺序,如果删除“securityManager.realms=$myRealm1,$myRealm2”,那么securityManager会按照realm声明的顺序进行使用(即无需设置realms属性,其会自动发现),当我们显示指定realm后,其他没有指定realm将被忽略,如“securityManager.realms=$myRealm1”,那么myRealm2不会被自动设置进去
  2. 1、变量名=全限定类名会自动创建一个类实例

    2、变量名.属性=值 自动调用相应的setter方法进行赋值

    3、$变量名 引用之前的一个对象实例

  • Authenticator及AuthenticationStrategy

  1. 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的更多相关文章

  1. spring boot / cloud (四) 自定义线程池以及异步处理@Async

    spring boot / cloud (四) 自定义线程池以及异步处理@Async 前言 什么是线程池? 线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务.线 ...

  2. Authenticator及AuthenticationStrategy

    Authenticator的职责是验证用户帐号,是Shiro API中身份验证核心的入口点: 如果验证成功,将返回AuthenticationInfo 验证信息:此信息中包含了身份及凭证:如果验证失败 ...

  3. Shiro笔记(四)Shiro的realm认证

    认证流程: 1.获取当前Subject.调用SecurityUtils.getSubject(); 2.测试当前用户是否已经被认证,即是否已经登录,调用Subject的isAurhenticated( ...

  4. 自定义shiro的Realm实现和CredentialsMatcher实现以及Token实现

    Realm是shiro比较核心的接口,简单说它的实现类就是校验用户输入的账号信息的地方.如果想自定义实现一般的配置文件如下: <!--自定义Realm 继承自AuthorizingRealm - ...

  5. 项目一:第十四天 1.在realm中动态授权 2.Shiro整合ehcache 缓存realm中授权信息 3.动态展示菜单数据 4.Quartz定时任务调度框架—Spring整合javamail发送邮件 5.基于poi实现分区导出

    1 Shiro整合ehCache缓存授权信息 当需要进行权限校验时候:四种方式url拦截.注解.页面标签.代码级别,当需要验证权限会调用realm中的授权方法   Shiro框架内部整合好缓存管理器, ...

  6. 走进AngularJs(四)自定义指令----(中)

    上一篇简单介绍了自定义一个指令的几个简单参数,restrict.template.templateUrl.replace.transclude,这几个理解起来相对容易很多,因为它们只涉及到了表现,而没 ...

  7. VSTO学习(四)——自定义Excel UI 转载

    本专题概要 引言 自定义任务窗体(Task Pane) 自定义选项卡,即Ribbon 自定义上下文菜单 小结 引言 在上一个专题中为大家介绍如何创建Excel的解决方案,相信大家通过从上面一个专题之后 ...

  8. Shiro - 自定义filterChainDefinitions和Realm

    在Spring Context中定义shiroFilter(org.apache.shiro.spring.web.ShiroFilterFactoryBean)时需要为其filterChainDef ...

  9. AngularJS学习笔记(四) 自定义指令

    指令(directive)是啥?简单来说就是实现一定功能的XXX...之前一直用的ng-model,ng-click等等都是指令.当我有一个ng没提供的需求的时候,就可以自定义个指令.指令的好处显而易 ...

随机推荐

  1. postgresql 的 .pgpass密码文件的使用

    pgpass 是 连接 postgresql 时使用的密码文件,通常位置为 ~/.pgpass.在使用某些组件时还真的必须使用.具体的格式为: hostname:port:database:usern ...

  2. 安装kvm安装虚拟机centos

    1 安装阿里云的镜像站 #将原来的镜像备份 cd /etc/yum.repos.d/ mkdir back mv CentOS-Base.repo ./back/ # 安装阿里的镜像 wget -O ...

  3. patch工具的使用

    1. 最简用法 patch -p1 < jello.patch

  4. keras损失函数

    keras文档:  http://keras.io/objectives/ mean_squared_error / mse  均方误差,常用的目标函数,公式为((y_pred-y_true)**2) ...

  5. 【转载】 第四范式首席科学家杨强:AlphaGo的弱点及迁移学习的应对(附视频)

    原文地址: https://www.jiqizhixin.com/articles/2017-06-02-2 ============================================= ...

  6. webdriver报不可见元素异常方法总结

    最近一直在学Selenium相关东西,学到webdriver这块,出现报不可见元素异常方法异常,后来网上找了好多相关资料都没搞定,也没看明白,最后发现是xpath中写了calss属性有问题.现在把学习 ...

  7. 几种主流浏览器内置http抓包工具软件使用方

    对于学习网站的人或者相关编程人员,经常需要用到http抓包工具来跟踪网页,但主流抓包软件如httpwatch.httpanalyzerstdv都是收费的,破解版往往也不稳定.实际上现在很多浏览器都内置 ...

  8. ABAP DEMO篇21 选择屏幕显示说明TEXT

    实现方式1: *&---------------------------------------------------------------------**& Report YCX ...

  9. Go 自定义包引入报错

    配置文件 GO111MODULE=on 设置为on时,go命令行会使用modules,而一点也不会去GOPATH目录下查找.但自定义包在 $GOPATH/github.com/winyh/strrev ...

  10. (2) Java SQL框架(java.sql.*)中常用接口详解

    Driver接口:定义了一个驱动程序接口,每一个数据库的JDBC driver都应该实现这个接口,用于访问对应的数据库.比如MySQL的driver为com.mysql.jdbc.Driver.Jav ...