Spring Security教程外篇(1)---- AuthenticationException异常详解
这个异常是在登录的时候出现错误时抛出的异常,比如账户锁定,证书失效等,先来看下AuthenticationException常用的的子类:
UsernameNotFoundException 用户找不到
BadCredentialsException 坏的凭据
AccountStatusException 用户状态异常它包含如下子类
AccountExpiredException 账户过期
LockedException 账户锁定
DisabledException 账户不可用
CredentialsExpiredException 证书过期
常见的异常就这几个,还有很多不再一一赘述,仅仅为了展示,对后续的阅读没有什么影响
用户登录验证的过滤器是UsernamePasswordAuthenticationFilter,它继承自AbstractAuthenticationProcessingFilter。
今天研究的是看Spring如何处理AuthenticationException这个异常的,异常的处理一般都是doFilter中处理的,所以首先看AbstractAuthenticationProcessingFilter的doFilter中的代码
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)throws IOException, ServletException {.......try {authResult = attemptAuthentication(request, response);if (authResult == null) {// return immediately as subclass has indicated that it hasn't completed authenticationreturn;}sessionStrategy.onAuthentication(authResult, request, response);} catch(InternalAuthenticationServiceException failed) {logger.error("An internal error occurred while trying to authenticate the user.", failed);unsuccessfulAuthentication(request, response, failed);return;}catch (AuthenticationException failed) {// Authentication failedunsuccessfulAuthentication(request, response, failed);return;}......}
从这段代码中我们看到Spring将异常捕获后交给了unsuccessfulAuthentication这个方法来处理(InternalAuthenticationServiceException也是AuthenticationException异常的子类,这是一个内部认证服务异常)
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,AuthenticationException failed) throws IOException, ServletException {SecurityContextHolder.clearContext();if (logger.isDebugEnabled()) {logger.debug("Authentication request failed: " + failed.toString());logger.debug("Updated SecurityContextHolder to contain null Authentication");logger.debug("Delegating to authentication failure handler " + failureHandler);}rememberMeServices.loginFail(request, response);failureHandler.onAuthenticationFailure(request, response, failed);}
unsuccessfulAuthentication又交给了failureHandler(AuthenticationFailureHandler)来处理,然后追踪failureHandler
private AuthenticationFailureHandler failureHandler = new SimpleUrlAuthenticationFailureHandler();
发现最终是由SimpleUrlAuthenticationFailureHandler这个类的onAuthenticationFailure方法来处理的,打开这个类,有两个核心方法
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,AuthenticationException exception) throws IOException, ServletException {if (defaultFailureUrl == null) {logger.debug("No failure URL set, sending 401 Unauthorized error");response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authentication Failed: " + exception.getMessage());} else {saveException(request, exception);if (forwardToDestination) {logger.debug("Forwarding to " + defaultFailureUrl);request.getRequestDispatcher(defaultFailureUrl).forward(request, response);} else {logger.debug("Redirecting to " + defaultFailureUrl);redirectStrategy.sendRedirect(request, response, defaultFailureUrl);}}}/*** Caches the {@code AuthenticationException} for use in view rendering.* <p>* If {@code forwardToDestination} is set to true, request scope will be used, otherwise it will attempt to store* the exception in the session. If there is no session and {@code allowSessionCreation} is {@code true} a session* will be created. Otherwise the exception will not be stored.*/protected final void saveException(HttpServletRequest request, AuthenticationException exception) {if (forwardToDestination) {request.setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception);} else {HttpSession session = request.getSession(false);if (session != null || allowSessionCreation) {request.getSession().setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception);}}}
从onAuthenticationFailure中我们可以看出,如果没有设置defaultFailureUrl就发出401错误。(SC_UNAUTHORIZED是一个常量值是401),如果设置了defaultFailureUrl,调用saveException方法后跳转到defaultFailureUrl页面。
forwardToDestination是是否是服务器跳转,默认使用重定向即客户端跳转。
saveException字面意思是保存异常信息,其实就是把异常信息写入request或者Session中。
如果使用服务器跳转则写入request,客户端跳转则写入Session。
而key是WebAttributes.AUTHENTICATION_EXCEPTION打开WebAttributes找到这个常量
public final class WebAttributes {public static final String ACCESS_DENIED_403 = "SPRING_SECURITY_403_EXCEPTION";public static final String AUTHENTICATION_EXCEPTION = "SPRING_SECURITY_LAST_EXCEPTION";public static final String WEB_INVOCATION_PRIVILEGE_EVALUATOR_ATTRIBUTE = WebAttributes.class.getName() + ".WEB_INVOCATION_PRIVILEGE_EVALUATOR_ATTRIBUTE";
}
发现其值为SPRING_SECURITY_LAST_EXCEPTION,这样的话我们就可以在页面上通过el表达式来获取到这个异常了
注意:saveException保存的是Session对象所以直接使用 ${SPRING_SECURITY_LAST_EXCEPTION}是获取不到异常信息的,需要使用${SPRING_SECURITY_LAST_EXCEPTION.message}
Spring Security教程外篇(1)---- AuthenticationException异常详解相关推荐
- SpringBoot非官方教程 | 第二篇:SpringBoot配置文件详解
springboot采纳了建立生产就绪Spring应用程序的观点. Spring Boot优先于配置的惯例,旨在让您尽快启动和运行.在一般情况下,我们不需要做太多的配置就能够让spring boot正 ...
- Spring Boot教程(十七)属性配置文件详解(2)
通过命令行设置属性值 相信使用过一段时间Spring Boot的用户,一定知道这条命令:java -jar xxx.jar --server.port=8888,通过使用–server.port属性来 ...
- Spring Security教程
Spring Security教程 Web系统中登录认证(Authentication)的核心就是凭证机制,无论是Session还是JWT,都是在用户成功登录时返回给用户一个凭证,后续用户访问接口需携 ...
- Spring Security 教程
Spring Security 教程 在这篇文章中,我们将讨论Spring框架 "安全性"模块基础知识.我们将在即将发布的帖子中开发一些简单而先进的示例. 现在,开发安全应用程序是 ...
- 循序渐进学spring security 第八篇,如何配置密码加密?是否支持多种加密方案?
文章目录 回顾 密码明文会带来什么问题? 如何加密? PasswordEncoder 加密接口 如何配置? 加密的密码在登录的时候是怎么校验的? 默认的加密是什么? DaoAuthentication ...
- 史上最简单的Spring Security教程(十九):AccessDecisionVoter简介及自定义访问权限投票器
为了后续对 AccessDecisionManager 的介绍,我们先来提前对 AccessDecisionVoter 做个简单的了解,然后,在捎带手自定义一个 AccessDecisionVoter ...
- 【STM32】STM32标准库与HAL库对照学习教程特别篇--系统时钟RCC详讲
[STM32]STM32标准库与HAL库对照学习教程特别篇--系统时钟RCC详讲 一.前言 二.时钟是什么 三.时钟树 1.时钟树图 2.时钟树讲解 左边部分 中间部分 右边部分 特殊部分 四.初始化 ...
- 【夯实Spring Cloud】Spring Cloud中使用Hystrix实现断路器原理详解(上)
本文属于[夯实Spring Cloud]系列文章,该系列旨在用通俗易懂的语言,带大家了解和学习Spring Cloud技术,希望能给读者带来一些干货.系列目录如下: [夯实Spring Cloud]D ...
- php laravel入口文件,Laravel学习教程之从入口到输出过程详解
php 的 Laravel学习教程之从入口到输出过程详解 本文主要给大家介绍了关于Laravel从入口到输出过程的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. I. 预备 ...
最新文章
- OpenCV+python:模板匹配
- Cannot add or update a child row:
- JZOJ 5456. 【NOIP2017提高A组冲刺11.6】奇怪的队列
- mysql的单个数据库物理迁移出现ERROR 1146 (42S02): Table 'xx' doesn't exist [问题点数:100分]...
- ios 动画 隐藏tabbar_UITabBarViewController 的底部 tabBar 隐藏
- 23种设计模式(5)-适配器模式
- 附录-系统环境、系统属性
- SSH启动失败解决方法
- Windows软件防火墙实现技术简述
- java xml注释多行_如何在XML中注释单行?
- 基于LabVIEW 2018开发的自动化测试系统源码,该系统模仿TestStand编写
- 计算机程序设计实验报告总结,c语言实验总结(大一c语言实验报告总结)
- LeeCode 130 DFS
- 考研题目 第五章 数组和广义表
- YARN原理及工作流程详解
- PMP知识点:项目成本管理计算公式
- SQL Server 索引碎片和填充因子
- 《网络攻防》第二周作业
- (OS 10038)在一个非套接字上尝试了一个操作 的解决办法
- Microblaze程序固化流程
热门文章
- Relational Graph Attention Network for Aspect-based Sentiment Analysis
- 数据结构与算法基础--王卓
- Adaptive Deconvolutional Networks for Mid and High Level Feature Learning(阅读)
- VGG19模型训练+读取
- linux oracle按钮乱码,oracle em 按钮乱码现象
- 数据结构--抽象数据类型三元组Triplet的表示和实现
- Windows CMD常用命令查询
- 局域网下怎样访问另一台电脑的服务
- STM32F103C8T6继电器驱动篇
- 我的JAVA面试题备忘录