通过前面对SpringSecurity安全过滤器工作原理的分析(SpringSecurity安全过滤器的工作原理),我们知道了SpringSecurity用户认证的工作原理流程大致为:SecurityContextPersistenceFilter过滤服务器负责管理基于会话的用户认证信息。UsernamePasswordAuthenticationFilter负责用户登录认证,认证成功后将认证信息写入SecurityContextHolder。FilterSecurityInterceptor负责验证当前用户是否符合当前请求的安全策略要求。所以我们知道用户身份验证是在UsernamePasswordAuthenticationFilter过滤器中完成的。如果我们要实现自定义的用户登录认证,我们只需要在UsernamePasswordAuthenticationFilter过滤器中想办法替换掉原来默认的用户认证流程,应该就可以了。接下来我们研究:什么是用户认证。UsernamePasswordAuthenticationFilter过滤器的默认身份验证过程。如何替换UsernamePasswordAuthenticationFilter默认的用户认证流程。什么是用户认证?其实我们不研究这个问题,只是声明一下,明确我们要研究的问题的主题。SpringSecurity官网的概述部分,在明确提到用户认证的时候,明确说明了什么是SpringSecurity:SpringSecurity是一个提供认证、授权和防范常见攻击的框架。可见用户认证是SpringSecurity的重要课题之一。把今天要研究的用户认证这个话题简单说一下:用户身份认证,就是让系统判断你是不是合法用户的过程。目前,我们在项目或系统中看到的最常用的身份认证方式是用户名和密码(或短信验证码)。用户身份认证实际上包括两部分:身份确认:通过登录完成。身份维护与验证:登录验证完成后,保存用户身份验证信息,以及后续用户访问过程中的验证问题。第一题比较简单明了,第二题会介绍两种不同的主流框架。主要区别在于如何保存用户身份认证信息:服务器端存储:最常见的会话方式。客户端持有:比如JWT的方式。我们今天要讨论的是身份认证的过程,忽略或者简化保存和持有身份信息的过程,也可以在服务端使用session提供的传统的和默认的springsecurity。通过终端持有用户身份认证信息的方式,将今天的研究课题集中在身份认证问题上。UsernamePasswordAuthenticationFilter过滤器的身份认证过程首先要认识几个概念:Authentication:或AuthenticationToken,默认实现为UsernamePasswordAuthenticationToken,用于保存请求的用户名、密码等信息,以及最终认证后的用户认证信息.AuthenticationManager:认证管理器发起认证,但他不完成认证,而是用他持有的AuthenticationProvider完成。AuthenticationProvider:同上。UserDetails:系统的合法用户信息。例如,你系统的合法用户存储在数据库中。那么在发起鉴权的过程中,需要从数据库中获取,保存到UserDetails中。相应的,有一个叫UserDetailsS??ervice的家伙负责这个东西。PasswordEncoder:顾名思义,就是一个密码编码器。系统用户的密码必须以密文形式保存在系统中。前台提交的信息通常是明文,需要通过PasswordEncoder进行校验。说白了,你的密码加密算法是在PasswordEncoder中实现的。差不多了,下面我们用上面的概念来说明UsernamePasswordAuthenticationFilter过滤器的用户登录认证过程。第一步是使用request生成UsernamePasswordAuthenticationToken。此时生成的UsernamePasswordAuthenticationToken对象中只有前端登录页面上传的用户名和密码,token还没有经过认证。我们假设前台发过来的用户叫:user。前台输入的密码是:123456。第二步获取AuthenticationManager进行鉴权。上面说了,他是manager,他不干活,AuthenticationProvider干活。第三步,AuthenticationProvider开始工作。他先获取UserDetailsS??ervice,让他获取系统中名为user的用户信息,返回UserDetails对象(假设获取到,对象名为sysUser)。第四步依旧是继续AuthenticationProvider,将前端发送过来的用户名和密码(目前持有的是UsernamePasswordAuthenticationToken对象),以及后台获取到的用户对象(sysUser),交给PasswordEncoder进行处理确认。第五步,AuthenticationProvider继续努力。如果认证通过(密码相同),则重新生成一个UsernamePasswordAuthenticationToken,这是一个已经通过认证的token。第六步,AuthenticationProvider完成工作,交给管理器AuthenticationManager,AuthenticationManager将结果交给过滤器UsernamePasswordAuthenticationFilter。第七步,filter将最终认证的UsernamePasswordAuthenticationToken保存在SecurityContextHolder中,以供后续filter,尤其是FilterSecurityInterceptor校验。UsernamePasswordAuthenticationFilter完成任务!如何替换UsernamePasswordAuthenticationFilter的默认用户认证过程标题太长,我有点不适应,但仅此而已。如果你去百度或谷歌这个问题,你会有很多不同的答案。我了解到,由于SpringSecurity本身就是Spring家族的一员,与Spring或者SpringBoot结合后,可以有多种方式为用户定制,所以我们可以选择一种是定制。任何能够实现您的目标而不会对您的项目产生负面影响的事情都是可行的。让我们开始实现这个目标。通过上面对UsernamePasswordAuthenticationFilter的工作过程的分析,我们首先可以设想一个思路:将上面第三步中的UserDetailsS??ervice替换掉,让我们自己的UserDetailsS??ervice来获取我们自己的用户。我认为这是一个相对简单的解决方案。当然你可以替换整个UsernamePasswordAuthenticationFilter,但是这样的话你就相当于替换了SpringSecurity的一个重要模块,你可以怀疑它是否还是SpringSecurity。由于文章篇幅,本文的分析原理将在下一篇文章中进行具体操作。上一篇SpringSecurity安全过滤器工作原理下一篇SpringSecurity自定义用户认证流程(二)
