• 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. c++ homework 1

    先交作业(急促) 电梯作业 elevator (不知道为啥,我BIN文件夹建立不了.) PTA练习 如图 如图

  2. Windows 自动定时执行任务的方法

    windows 自动定时执行任务的几种实现方法   Task Schedul Windows自动定时执行任务,常见的方法有三种: Windows 任务计划程序 Windows Service SQL ...

  3. CDH 安装的博客地址记录

    1. 集群环境配置 https://www.cnblogs.com/yinzhengjie/articles/11019333.html 2. 二进制方法安装 https://www.cnblogs. ...

  4. 如何在linux中测试i2c slave模式驱动的功能?

    1. 硬件要求 1.1 需要两台机器,一台作为i2c master(记为M),另一台作为i2c slave(记为S) 1.2 使用杜邦线连接两台机器的i2c信号线 2. 使能内核选项CONFIG_I2 ...

  5. 5G && 物联网

    可打电话的 2G.能够上网的 3G.满足移动互联网用户需求的 4G 相比,逐步可以商用的 5G 在多重性能上更胜一筹,如 高数据率: 低延迟: 更节能: 有效地降低通信成本: 具备更高的系统容量: 更 ...

  6. sed替换 - 含反斜杠(/)和Shell变量

    sed替换 - 含反斜杠(/)和Shell变量 摘自: https://blog.csdn.net/zhenyongyuan123/article/details/6616263 2011年07月19 ...

  7. python安装lnmp

    #!/usr/bin/python # -*- coding:utf-8 -*- # 注意:本实验用root用户.已经安装python3.6.5 用pycharm运行,首先把nginx安装包放在 /u ...

  8. node.js连接DB2实现fetchRows一行一行获取sql的源码

    参见程序中的queryResult那部分: /* * This example demonstrates how to fetch a single row from a large table * ...

  9. 【Leetcode_easy】606. Construct String from Binary Tree

    problem 606. Construct String from Binary Tree 参考 1. Leetcode_easy_606. Construct String from Binary ...

  10. iOS-objective-c产生随机数的方法

    objective-c 中三种产生随机数的方法 //arc4random() 比较精确不需要生成随即种子 //通过arc4random() 获取0到x-1之间的整数的代码如下:     int val ...