Spring Security小教程 Vol 3. 身份验证的入口-AbstractAuthenticationProcessingFilter
前言
结合上一期我们介绍的AuthenticationManager为入口的身份验证的核心模块,我们这次讨论的是为了使SpringSecurity对Spring Web项目提供支持,作为验证请求入口的。
第三期 Authentication核心简介
本期的任务清单
- AbstractAuthenticationProcessingFilter的依赖组件;
- AbstractAuthenticationProcessingFilter依赖组件的主要职责和相关设计动机。
1. AbstractAuthenticationProcessingFilter处理Request及与AuthenticationManager交互的流程
AbstractAuthenticationProcessingFilter的主要职责和依赖组件
了解AbstractAuthenticationProcessingFilter大概是干嘛的的最简单的方法就是直接去读api-doc。
Abstract processor of browser-based HTTP-based authentication requests.
官方文档说的很明白了:处理基于浏览器交互的HTTP验证请求。所以AbstractAuthenticationProcessingFilter的职责也就非常明确——处理所有HTTP Request和Response对象,并将其封装成AuthenticationMananger可以处理的Authentication。并且在身份验证成功或失败之后将对应的行为转换为HTTP的Response。同时还要处理一些Web特有的资源比如Session和Cookie。总结成一句话,就是替AuthenticationMananger把所有和Authentication没关系的事情全部给包圆了。
继续读JavaDoc可以得知AbstractAuthenticationProcessingFilter为了完成组织上交代的与浏览器和HTTP请求的验证任务。它将大任务拆成了几个子任务并交给了以下组件完成:
- AuthenticationManager用于处理身份验证的核心逻辑;
AuthenticationSuccessHandler
用于处理验证成功的后续流程;AuthenticationFailureHandler
用于处理失败的后续流程;- 在验证成功后发布一个名为
InteractiveAuthenticationSuccessEvent
的事件通知给到应用上下文,用于告知身份验证已经成功; - 因为是基于浏览器所以相关的会话管理行为交由
SessionAuthenticationStrategy
来进行实现。 - 文档上还有一点没有写出来的是,如果用户开启了类似“记住我”之类的免密码登录,AbstractAuthenticationProcessingFilter还有一个名为RememberMeServices来进行管理。
AbstractAuthenticationProcessingFilter的验证流程
AbstractAuthenticationProcessingFilter本质上还是个Filter,其核心的业务入口方法就是doFilter方法:
这里我们先设置一个问题,然后带着问题去分析AbstractAuthenticationProcessingFilter的doFilter都是怎么设计解决这些问题的?
- 怎么判断当前的请求是需要被验证访问的?
- 如何进行身份验证?
- 如何进行会话验证?动机是什么?
- 成功和失败的后续流程都在干什么?
- Remember-Me功能实现流程是什么?
- 如何在其他服务中监听验证成功的事件?
问题1. 怎么判断当前的请求是需要被验证访问的?
在正式进行身份之前,doFilter会通过Security中的。尝试查找是否有匹配记录。 我们回顾下之前我们写过的访问控制的代码:
@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests()// inde.html对应的url允许所任人访问.antMatchers("/").permitAll()// user.html对应的url,则需要用户有USER的角色才可以访问.antMatchers("/user").hasRole("USER").and().formLogin();}
复制代码
其中的matcher的规则便会在这个流程中预先被检查,如果需要进行身份验证则会进行写一个阶段:对请求进行必要的身份验证。
问题2. 如何进行身份验证?
doFilter中通过调用自己的attemptAuthentication方法,但并不进行身份验证的逻辑处理,而是委托AuthenticationManager去完成相关的身份验证流程。AbstractAuthenticationProcessingFilter将HttpServletRequest包装成了Authentication对象与核心的AuthenticationManager进行交互。这样的设计可以使AuthenticationManager不感知外部的Web环境,从而使Security不仅可以支持Web应用,同时也可以被所有Java应用进行使用——只要客制化外部参与并将其封装成Authentication与AuthenticationManager的进行身份验证。
这里还需要注意的是在AuthenticationManager中实际完成身份验证任务并不是AuthenticationManager它自己身。而是将相关的任务针对每一种身份验证协议的AuthenticationProvider去完成相关的身份验证工作。
问题3. 如何进行会话验证管理?动机是什么?
第一个概念会话验证是什么的一个概念?我们知道HTTP的请求实际上是无状态的,浏览器为了使HTTP之间能使用同一会话进行操作,在Java Web中通常会将Web容器(特指Tomcat)的JSESSIONID写入请求的cookie中一同发送。
而服务端中通过中的JSESSIONID是通过request.getSession().getId()获取的,这样便使本来无状态的HTTP通过客户端的cookie中JSESSIONID与服务端的Session关联了起来。 但是从安全角度来说这样匹配机制存在许多问题,最简单的问题就是Session id在整个会话失效之间是不会变更的,这样就可以通过身份验证通过后获取了Session id从而通过其他客户端伪造cookie与服务端进行交互。有兴趣的同学可以针对这问题去了解下客户端cookie、服务端session以及一些CSRF攻击的介绍。本人比较推荐这篇http://hengyunabc.github.io/slides/cookie-and-session-and-csrf.html#1。
针对不同的会话管理策略场景,Security也提供了相应的实现,有机会再单独开一篇单独来介绍相关的策略。这边就先了解下,在完成了AuthenticationManager的身份验证后,还会对其进行必要的会话验证。
问题4. 成功和失败的后续流程都在干什么?
验证成功之后AuthenticationManager会返回一个通过UserDetail构造并且附带上了所有授权信息的Authentication对象。 而验证失败的话则会抛出,AbstractAuthenticationProcessingFilter捕获异常之后进行进行验证失败的处理。 成功的后续操作最主要的一个操作便是,通过SecurityContextHolder将本次验证之后的Authentication对象塞到当前的SecurityContext中。在后续的操作中如需要使用到Authentication身份信息,则可以直接通过SecurityContextHolder去获取。
//成功后设置上下文二SecurityContextHolder.getContext().setAuthentication(authResult);//后续操作可以从上下文中获取身份信息SecurityContextHolder.getContext().getAuthentication();
复制代码
然后再通过ApplicationEventPublisher发送验证成功的事件信息供其他相关监听器进行相关操作。
操作失败就简单了,既然成功是重新将最新的Authentication对象塞到SecurityContext上下文中,失败便是直接清空了上下文,让其Authentication对象变得“一无所有”。
而其他的对于request的额外操作则可以分别通过与两个接口去设置相关操作。
那么哪些工作属于验证成功后还需要额外操作的呢?举个最简单的例子,在用户想访问一个受限的资源,他首先被重定向掉了登录页面让其输入用户名和密码,而在其验证成功之后,那么他是讲指向到指定的某一个页面还是重定向到本次操作本来想访问的受限资源的路径呢? 这些相关的操作便是在AuthenticationSuccessHandler中进行完成的。 同样的如果登录失败需要做一些除了身份验证以外,有需要感知HTTP请求、响应对象的操作,同样的也可以在AuthenticationFailureHandler中进行完成。
问题5. Remember-Me功能实现流程是什么?
Remember-Me是指网站能够在Session之间记住登录用户的身份,具体来说就是我成功认证一次之后在一定的时间内我可以不用再输入用户名和密码进行登录了,系统会自动给我登录。这通常是通过服务端发送一个cookie给客户端浏览器,下次浏览器再访问服务端时服务端能够自动检测客户端的cookie,根据cookie值触发自动登录操作。 实现方式有很多种,一般来说最简单的实现就是将用户名与一些其他字符组合进行编码,然后服务端解码之后提取出相关其中的用户名,通过UserDetailsService获取相关用户信息的用户验证方式。 Spring Security中提供了两种Remember-Me机制进行使用,如果有其他实现方式也可以通过继承AbstractRememberMeServices类进行扩展。请一定牢记Remember-Me机制的现实是依赖浏览器Cookie的,在默认情况下SpringSecurity会将编码后的字符串存于Cookie中的remember-me键位。
#问题6. 如何在其他服务中监听验证成功的事件
在完整整个验证流程之后,AbstractAuthenticationProcessingFilter还会通过Spring容器的事件发布器发射一个。如果需要在应用其他监听器上处理相关验证成功后操作。我们可以通过Spring中的@EventListener监听InteractiveAuthenticationSuccessEvent事件便可以实现。 写一个示例,如果我们想在每个用户登录成功后,在控制台打印出登录用户的用户名。
@Component
public class AuthenticationListener {@EventListenerpublic void register(InteractiveAuthenticationSuccessEvent event){//获取登录成功的Authentication对象Authentication authentication = event.getAuthentication();//打印用户名System.out.println("@EventListener注册信息,用户名:"+authentication.getName());}
}
复制代码
结尾
本期花了很大的篇幅介绍了整个Web验证流程的核心组件AbstractAuthenticationProcessingFilter。下一期我们将结合他最常用的实现类UsernamePasswordAuthenticationFilter做一个讲解,希望通过讲解UsernamePasswordAuthenticationFilter实现使大家了解客制化一个验证协议需要注意的细节。 我们下期再见。
转载于:https://juejin.im/post/5c98b0d2e51d4543f02ca7f7
Spring Security小教程 Vol 3. 身份验证的入口-AbstractAuthenticationProcessingFilter相关推荐
- Spring Security小教程 Vol 2. Authentication核心组件介绍
前言 上一期我们介绍了如何最简单的为一个SpringBoot应用添加Spring Security框架,并使其为应用完成用户鉴权和访问控制的授权服务. 这一期我们将聚焦在用户鉴权部分,用户鉴权又可以从 ...
- 如何使用Java和XML Config在Spring Security中启用HTTP基本身份验证
在上一篇文章中,我向您展示了如何在Java应用程序中启用Spring安全性 ,今天我们将讨论如何使用Spring Security 在Java Web应用程序中启用Basic HTTP身份验证 . 如 ...
- 使用Spring Security对RESTful服务进行身份验证
1.概述 本文重点介绍如何针对提供安全服务的安全REST API进行身份验证 -主要是RESTful用户帐户和身份验证服务. 2.目标 首先,让我们看一下参与者-典型的启用了Spring Securi ...
- 双因素认证java_使用spring security oauth2进行双因素身份验证
我无法使接受的解决方案有效 . 我一直在研究这个问题,最后我通过使用这里解释的想法并在这个帖子上写了我的解决方案"null client in OAuth2 Multi-Factor Aut ...
- Spring Security 示例教程
Spring Security 示例教程 Spring Security提供了在Web应用程序中执行身份验证和授权的方法.我们可以在任何基于servlet的Web应用程序中使用spring secur ...
- Spring Security示例教程
Spring Security provides ways to perform authentication and authorization in a web application. We c ...
- Spring Security系列教程03--创建SpringSecurity项目
前言 在上一章节中,一一哥 已经带大家认识了Spring Security,对其基本概念已有所了解,但是作为一个合格的程序员,最关键的肯定还是得动起手来,所以从本篇文章开始,我就带大家搭建第一个Spr ...
- java ldap操作实例_Java Spring Security示例教程中的2种设置LDAP Active Directory身份验证的方法...
java ldap操作实例 LDAP身份验证是世界上最流行的企业应用程序身份验证机制之一,而Active Directory (Microsoft为Windows提供的LDAP实现)是另一种广泛使用的 ...
- Java Spring Security示例教程中的2种设置LDAP Active Directory身份验证的方法
LDAP身份验证是全球范围内最流行的企业应用程序身份验证机制之一,而Active Directory (Microsoft针对Windows的LDAP实现)是另一种广泛使用的LDAP服务器. 在许多项 ...
最新文章
- 华中科大计算机冯丹,华中科大南加校友会欢迎母校代表团
- python能爬视频吗_Python爬取视频(其实是一篇福利)
- 8、ShardingSphere 之 Sharding-Proxy 实现分库分表
- Windows 下 MySQL-python 的安装
- 计算机无法用u盘重装系统,没有u盘电脑开不了机重装系统的方法步骤详细教程 - 系统家园...
- 菜鸟Linux系列:[4]SSH免密码登陆远程服务器
- 彻底火了!这份Python学习贴,90%程序员用的上!
- 转:NAT traversal 的概念
- linux定位异常前后日志信息
- 2019-C语言二级考试题库
- python词频统计三国演义_python实例:三国演义TXT文本词频分析
- Word中把竖排文字里的数字变横向
- 清除逻辑库内的所有数据集
- python虚拟宠物猫
- 读书笔记:PHP和MySQL高性能应用开发 (2019.2.20-2019.3.4)
- 5G融合通信网关(应急通讯、车载通讯、视频传输)
- Vue3悬浮返回主页按钮设计与实现
- 指尖江湖李忘生鸿蒙初开,剑网3指尖江湖李忘生全面评价
- win10计算机配置在哪里打开,详细教您win10设备管理器在哪打开
- 对接支付宝手机网站支付接口,alin10071