问题背景 
在实现多Realm时,扩展了ModularRealmAuthenticator 和 UsernamePasswordToken,于是在MyAuthenticationToken token = (MyAuthenticationToken) authenticationToken时出现了转型异常。

扩展ModularRealmAuthenticator 的代码如下:

public class MyModularRealmAuthenticator extends ModularRealmAuthenticator {

    @Override
public AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {
MyAuthenticationToken token = (MyAuthenticationToken) authenticationToken;
String loginType = token.getLoginType();
Collection<Realm> realms = getRealms();
Collection<Realm> authRealms = new ArrayList<>();
for(Realm realm : realms){
if(realm.getName().equals(loginType)){
authRealms.add(realm);
}
} if(authRealms.size() == 1){
return doSingleRealmAuthentication(authRealms.iterator().next(), token);
} else {
return doMultiRealmAuthentication(authRealms, token);
}
} }

扩展UsernamePasswordToken的代码如下:

public class MyAuthenticationToken extends UsernamePasswordToken {

    private String loginType;

    public MyAuthenticationToken(final String username, final String password, String loginType){
super(username, password);
this.loginType = loginType;
} public String getLoginType() {
return loginType;
} public void setLoginType(String loginType) {
this.loginType = loginType;
}
}

从上面的扩展中我们看到,没有地方使用我们的自己扩展的MyAuthenticationToken类,只是转型而已,并没有去实例化它,这才是引起问题的根源,问题发现了要如何解决它呢?我们在配置的使用并并未制定表单过滤器,此时默认使用的是FormAuthenticationFilter,而Token默认使用的也是UsernamePasswordToken,由此看来,我们扩展的MyAuthenticationToken就成了摆设,此时就要想办法如何将我们的扩展引用到程序里去呢? 
既然默认的是UsernamePasswordToken,那么是如何将UsernamePasswordToken注入的呢?我们进入默认的Filter(FormAuthenticationFilter)可以看到createToken,这个是创建Token的,那么似乎可以和我们的Token搭上边了,FormAuthenticationFilter中的createToken如下:

protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {
String username = this.getUsername(request);
String password = this.getPassword(request);
return this.createToken(username, password, request, response);
}

我们发现期间又调用了createToken,此createToken为父类的方法,我们可以看到FormAuthenticationFilter的声明为 public class FormAuthenticationFilter extends AuthenticatingFilter ,也即内部调用的token为AuthenticatingFilter的实现,继续看AuthenticatingFilter中的createToken实现,而createToken中又调用了自身createToken的重载,源码如下:

protected AuthenticationToken createToken(String username, String password, ServletRequest request, ServletResponse response) {
boolean rememberMe = this.isRememberMe(request);
String host = this.getHost(request);
return this.createToken(username, password, rememberMe, host);
} protected AuthenticationToken createToken(String username, String password, boolean rememberMe, String host) {
return new UsernamePasswordToken(username, password, rememberMe, host);
}

可以看到在重载的createToken中,UsernamePasswordToken终于现身了,那么此时,我们可以通过扩展FormAuthenticationFilter并重新createToken将我们扩展的Token引入即可,以下为扩展的FormAuthenticationFilter:

public class MyFormAuthenticationFilter extends FormAuthenticationFilter {

    @Override
protected MyAuthenticationToken createToken(ServletRequest request, ServletResponse response) {
String username = getUsername(request);
String password = getPassword(request);
String loginType = request.getParameter("loginType");
if("sys".equals(loginType)){
return new MyAuthenticationToken(username, password, "sys");
} else {
return new MyAuthenticationToken(username, password, "wx");
}
} }

扩展完成后,需要配置默认的过滤器为我们的扩展,shiro的配置如下:

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="/login" />
<property name="successUrl" value="/index"/>
<property name="unauthorizedUrl" value="/403"/>
<property name="filterChainDefinitions">
<value>
/favicon.ico = anon
/logout = logout
/** = authc
</value>
</property>
<property name="filters">
<map>
<entry key="authc" value-ref="myFormAuthenticationFilter" />
</map>
</property>
</bean> <bean id="myFormAuthenticationFilter" class="com.yuxiao.springboot.springbootmybatis.config.shiro.filter.MyFormAuthenticationFilter"/>

实现多Realm时,可能会出现的问题的更多相关文章

  1. hibernate有关联关系删除子表时可能会报错,可以用个clear避免错误

    //清除子表数据 public SalesSet removeSalesSetDistributor(SalesSet salesSet ){ List<SalesSetDistributor& ...

  2. Shiro自定义Realm时用注解的方式注入父类的credentialsMatcher

    用Shiro做登录权限控制时,密码加密是自定义的. 数据库的密码通过散列获取,如下,算法为:md5,盐为一个随机数字,散列迭代次数为3次,最终将salt与散列后的密码保存到数据库内,第二次登录时将登录 ...

  3. MySQL查询语句练习题(面试时可能会遇到哦!)

    Sutdent表的定义 字段名 字段描述 数据类型 主键 外键 非空 唯一 自增 Id 学号 INT(10) 是 否 是 是 是 Name 姓名 VARCHAR(20) 否 否 是 否 否 Sex 性 ...

  4. 安装ubuntu server时可能会需要的配置

    1.修改源 笔者比较习惯用163的源,配置如下: sudo vi /etc/apt/sources.list 163源为: deb http://mirrors.163.com/ubuntu/ pre ...

  5. 用AJAX传值参数是中文时可能会乱码

    1.ajax代码 function SelectSemesterBySchYear() { // alert('sssssss'); var temp1 = document.getElementBy ...

  6. 使用Spring配置shiro时,自定义Realm中属性无法使用注解注入解决办法

    先来看问题    纠结了几个小时终于找到了问题所在,因为shiro的realm属于Filter,简单说就是初始化realm时,spring还未加载相关业务Bean,那么解决办法就是将springmvc ...

  7. 手把手教你从Core Data迁移到Realm

    来源:一缕殇流化隐半边冰霜 (@halfrost ) 链接:http://www.jianshu.com/p/d79b2b1bfa72 前言 看了这篇文章的标题,也许有些人还不知道Realm是什么,那 ...

  8. 手把手教你从 Core Data 迁移到 Realm

    前言 看了这篇文章的标题,也许有些人还不知道Realm是什么,那么我先简单介绍一下这个新生的数据库.号称是用来替代SQLite 和 Core Data的.Realm有以下优点: 使用方便 Realm并 ...

  9. Shiro探索1. Realm

    1. Realm 是什么?汉语意思:领域,范围:王国:这个比较抽象: 简单一点就是:Realm 用来对用户进行认证和角色授权的 再简单一点,一个用户怎么判断它有没有登陆?这个用户是什么角色有哪些权限? ...

随机推荐

  1. 趣图:这是拿offer极高的面试经验

      扩展阅读 趣图:面试谈薪资就要这种底气 趣图:IT培训出来找工作 趣图:这是招聘超神级别的程序员?

  2. P4395 [BOI2003]Gem 气垫车

    树形dp 首先,我们可以考虑dp,把这个问题看成一个树的染色问题,用dp[i][j]表示以i为根节点,将树染成第i种颜色的最小代价,那么我们可以得到j的最大值是(log(maxn)/log(2)+1) ...

  3. 后端开发实践:Spring Boot项目模板

    在我的工作中,我从零开始搭建了不少软件项目,其中包含了基础代码框架和持续集成基础设施等,这些内容在敏捷开发中通常被称为"第0个迭代"要做的事情.但是,当项目运行了一段时间之后再来反 ...

  4. LRU Cache & Bloom Filter

    Cache 缓存 1. 记忆 2. 空间有限 3. 钱包 - 储物柜 4. 类似背代码模板,O(n) 变 O(1)     LRU Cache 缓存替换算法 1. Least Recently Use ...

  5. 00 你的第一个C语言程序

    C语言简介 C 语言是一种通用的.面向过程式的计算机程序设计语言,即编程语言. 为移植和开发 UNIX 操作系统,丹尼斯·里奇于1972年在贝尔电话实验室设计开发了 C 语言的第一个版本. C 语言同 ...

  6. 【题解】CF1426E Rock, Paper, Scissors

    题目戳我 \(\text{Solution:}\) 考虑第二问,赢的局数最小,即输和平的局数最多. 考虑网络流,\(1,2,3\)表示\(Alice\)选择的三种可能性,\(4,5,6\)同理. 它们 ...

  7. WebStrom配置TypeScript开发环境

    安装NodeJS node.js下载地址:https://nodejs.org/en/download/ 安装TypeScript npm install typescripot -g 新建tscon ...

  8. CSG:清华大学提出通过分化类特定卷积核来训练可解释的卷积网络 | ECCV 2020 Oral

    论文提出类特定控制门CSG来引导网络学习类特定的卷积核,并且加入正则化方法来稀疏化CSG矩阵,进一步保证类特定.从实验结果来看,CSG的稀疏性能够引导卷积核与类别的强关联,在卷积核层面产生高度类相关的 ...

  9. for循环迭代可迭代对象

    模仿for循环迭代可迭代对象,# for i in Iterable:# iterable >>> 迭代器.iterator# 可迭代对象 iterable# 迭代器.iterato ...

  10. 达梦产品技术支持培训-day7-DM8数据库备份与还原-原理

    (本文部分内容摘自DM产品技术支持培训文档,如需要更详细的文档,请查询官方操作手册,谢谢) 1.DM8备份还原简介 1.1.基本概念 (1)表空间与数据文件 ▷ DM8表空间类型: ▷ SYSTEM ...