shiro权限框架,用户登录方法的subject.login(token)会进入自定义的UserNamePasswordRealm类的doGetAuthenticationInfo身份验证方法

通常情况,doGetAuthenticationInfo写法如下:

@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
User loginUser = userService.getUserByName(token.getUsername());
if (ObjectUtils.isEmpty(loginUser)) {
throw new UnknownAccountException();
}
if(!loginUser.getPassWord().equals(MD5Util.md5s(String.valueOf(token.getPassword())))){
throw new IncorrectCredentialsException();
}
//其他各种验证
。。。
}

login登录方法:

@ResponseBody
@RequestMapping(value = "/login", method = RequestMethod.POST)
public String doUserLogin(User user, HttpServletRequest request, Model model) {
...
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(user.getUserName(), user.getPassWord());
try {
subject.login(token);
} catch (UnknownAccountException uae) { } catch (IncorrectCredentialsException ice) { } catch (LockedAccountException lae) { } catch (ExcessiveAttemptsException eae) { } catch (AuthenticationException ae) { }
...
}

可是最近一次项目,发现通用的方法行不通了,doGetAuthenticationInfo方法抛出的各种异常如UnknownAccountException(包括自定义的异常),外部都无法准确捕捉。

外部login捕捉的异常统一被改写为 AuthenticationException异常(IncorrectCredentialsException等异常的父类),且异常的msg内容也被改写。内容如下:

原因在subject.login(token)的源码里,源码有这么一段:

我们进入doSingleRealmAuthentication方法,可以看见方法里面外抛了UnknownAccountException等异常。

所以如果项目中只定义了一个realm,比如用来进行登录的身份验证,外部是可以正常捕捉的。

但是此次项目我定义了两个realm,一个用来进行登录的身份验证,另一个用来登录后,验证各种请求携带的的token。

我们进入doMultiRealmAuthentication方法,内容如下

再进入afterAllAttempts的实现类,如图5。

发现抛出的异常都被统一改为AuthenticationException异常,且msg也被改写,正如图1所示。

结论

外部无法捕捉doGetAuthenticationInfo方法抛出的异常,原因在于源码,而不是自己的代码有问题。

如果没有改写源码的本事,那么外部想要捕捉各种异常,并在前端显示各种提示语,怎么办?

我的临时解决方法是,doGetAuthenticationInfo只用来验证用户名和密码,

外部直接捕捉AuthenticationException异常,其他的各种验证从doGetAuthenticationInfo方法移至login。

外部无法捕捉Realm的doGetAuthenticationInfo方法抛出的异常的更多相关文章

  1. JUnit 判断方法抛出的异常

    :比方案1更详细,可以进一步判断抛出的异常的报错信息是否符合预期 不用上面那个属性,用 try - catch(因为判断了报错信息,所以不用判断异常的类型了吧) ( 注释:MyAssert类是我自定义 ...

  2. 【Java】ArrayList 的 toArray() 方法抛出 ClassCastException 异常

    第一次用这个方法,结果冒出个莫名其妙的异常来: String[] names = (String[]) mTags.toArray(); 结果会抛出 java.lang.ClassCastExcept ...

  3. Json lib集成stucts2的使用方法 抛出 NestableRuntimeException异常的解决办法

    首先贴出struts 2.3.16需要导入的包 因为使用的是2.3 版本,必须要导入这个包,否则会报java.lang.NoClassDefFoundError: org/apache/commons ...

  4. Effective Java 第三版——74. 文档化每个方法抛出的所有异常

    Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...

  5. “全栈2019”Java异常第十一章:重写方法时只能抛出父类异常子集

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java异 ...

  6. 在SpringMVC中,当Json序列化,反序列化失败的时候,会抛出HttpMessageNotReadableException异常, 当Bean validation失败的时候,会抛出MethodArgumentNotValidException异常,因此,只需要在ExceptionHandler类中添加处理对应异常的方法即可。

    在SpringMVC中,当Json序列化,反序列化失败的时候,会抛出HttpMessageNotReadableException异常, 当Bean validation失败的时候,会抛出Method ...

  7. 应该抛出什么异常?不应该抛出什么异常?(.NET/C#)

    我在 .NET/C# 建议的异常处理原则 中描述了如何 catch 异常以及重新 throw.然而何时应该 throw 异常,以及应该 throw 什么异常呢? 究竟是谁错了? 代码中从上到下从里到外 ...

  8. Java中主线程如何捕获子线程抛出的异常

    首先明确线程代码的边界.其实很简单,Runnable接口的run方法所界定的边界就可以看作是线程代码的边界.Runnable接口中run方法原型如下: public void run(); 而所有的具 ...

  9. Response.End抛出ThreadAbortException 异常

    最近在写程序过程中遇到了一个匪夷所思的错误:Response.End()方法抛出了ThreadAbortException异常,我的代码如下: public void doResponse(){ st ...

随机推荐

  1. C++中的类继承(1) 三种继承方式

    继承是使代码可以复用的重要手段,也是面向对象程序设计的核心思想之一.简单的说,继承是指一个对象直接使用另一对象的属性和方法.继承呈现了 面向对象程序设 计的层次结构, 体现了 由简单到复杂的认知过程. ...

  2. 基于Spring开发——自定义标签及其解析

    1. XML Schema 1.1 最简单的标签 一个最简单的标签,形式如: <bf:head-routing key="1" value="1" to= ...

  3. Apache Beam 剖析

    1.概述 在大数据的浪潮之下,技术的更新迭代十分频繁.受技术开源的影响,大数据开发者提供了十分丰富的工具.但也因为如此,增加了开发者选择合适工具的难度.在大数据处理一些问题的时候,往往使用的技术是多样 ...

  4. 深入tornado中的协程

    tornado使用了单进程(当然也可以多进程) + 协程 + I/O多路复用的机制,解决了C10K中因为过多的线程(进程)的上下文切换 而导致的cpu资源的浪费. tornado中的I/O多路复用前面 ...

  5. MongoDB基础教程系列--第七篇 MongoDB 聚合管道

    在讲解聚合管道(Aggregation Pipeline)之前,我们先介绍一下 MongoDB 的聚合功能,聚合操作主要用于对数据的批量处理,往往将记录按条件分组以后,然后再进行一系列操作,例如,求最 ...

  6. APICloud框架—db数据库模块

    db数据库模块 db 模块封装了手机常用数据库 sqlite 的增删改查语句,可实现数据的本地存储,极大的简化了数据持久化问题,本模块已支持同步接口. 官方文档地址 打开/新建一个数据库 functi ...

  7. bit ( 比特 )和 Byte(字节)的关系 以及 网速怎么算

    今天来整理一下存储单位和网速的知识. 最近几天家里网不太好,所以就了解了一下网速和电脑的存储单位的关系. 一.存储单位的bit 和 Byte 1.bit(比特) bit也就是我们不一定听说过的比特,大 ...

  8. Unity3D 预备知识:C#与Lua相互调用

    在使用Unity开发游戏以支持热更新的方案中,使用ULua是比较成熟的一种方案.那么,在使用ULua之前,我们必须先搞清楚,C#与Lua是怎样交互的了? 简单地说,c#调用lua, 是c# 通过Pin ...

  9. 串口屏与触摸屏人机界面组态软件HMIMaker介绍

    串口屏与触摸屏人机界面组态软件HMIMaker介绍 触摸屏人机界面组态软件HMIMaker,是一款基于ARM架构的嵌入式控制系统开发的嵌入式软件,专业应用于触摸屏的二级界面开发,具有单片机协议,mod ...

  10. lua metatable(元表)

    lua metatable (元表) 概述 普通 table 类型的表仅能够做一些单表操作, 无法进行一些特殊的以及两个表的操作, 比如 table1 + table2, print(table3) ...