图解Spring Security 中用户是如何实现登录的

 更新时间:2020年07月27日 11:35:00   作者:码农小胖哥  
这篇文章主要介绍了图解Spring Security 中用户是如何实现登录的,文中通过示例代码和图片介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

1. 前言

欢迎阅读Spring Security 实战干货系列文章,在集成Spring Security安全框架的时候我们最先处理的可能就是根据我们项目的实际需要来定制注册登录了,尤其是Http登录认证。根据以前的相关文章介绍,Http登录认证由过滤器UsernamePasswordAuthenticationFilter 进行处理。我们只有把这个过滤器搞清楚才能做一些定制化。今天我们就简单分析它的源码和工作流程。

2. UsernamePasswordAuthenticationFilter 源码分析

UsernamePasswordAuthenticationFilter 继承于AbstractAuthenticationProcessingFilter(另文分析)。它的作用是拦截登录请求并获取账号和密码,然后把账号密码封装到认证凭据UsernamePasswordAuthenticationToken中,然后把凭据交给特定配置的AuthenticationManager去作认证。源码分析如下:

public class UsernamePasswordAuthenticationFilter extends
  AbstractAuthenticationProcessingFilter {
 // 默认取账户名、密码的key
	public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "username";
	public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "password";
 // 可以通过对应的set方法修改
	private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;
	private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY;
 // 默认只支持 POST 请求
	private boolean postOnly = true;
 
 // 初始化一个用户密码 认证过滤器 默认的登录uri 是 /login 请求方式是POST
 public UsernamePasswordAuthenticationFilter() {
  super(new AntPathRequestMatcher("/login", "POST"));
 }

 // 实现其父类 AbstractAuthenticationProcessingFilter 提供的钩子方法 用去尝试认证
 public Authentication attemptAuthentication(HttpServletRequest request,
   HttpServletResponse response) throws AuthenticationException {
  // 判断请求方式是否是POST
  if (postOnly && !request.getMethod().equals("POST")) {
   throw new AuthenticationServiceException(
    "Authentication method not supported: " + request.getMethod());
  }
  
  // 先去 HttpServletRequest 对象中获取账号名、密码
  String username = obtainUsername(request);
  String password = obtainPassword(request);

  if (username == null) {
   username = "";
  }

  if (password == null) {
   password = "";
  }

  username = username.trim();

  // 然后把账号名、密码封装到 一个认证Token对象中,这是就是一个通行证,但是这时的状态时不可信的,一旦通过认证就变为可信的
  UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
   username, password);

  // 会将 HttpServletRequest 中的一些细节 request.getRemoteAddr() request.getSession 存入的到Token中
  setDetails(request, authRequest);

  // 然后 使用 父类中的 AuthenticationManager 对Token 进行认证 
  return this.getAuthenticationManager().authenticate(authRequest);
 }
 // 获取密码 很重要 如果你想改变获取密码的方式要么在此处重写,要么通过自定义一个前置的过滤器保证能此处能get到
 @Nullable
 protected String obtainPassword(HttpServletRequest request) {
  return request.getParameter(passwordParameter);
 }

  // 获取账户很重要 如果你想改变获取密码的方式要么在此处重写,要么通过自定义一个前置的过滤器保证能此处能get到
 @Nullable
 protected String obtainUsername(HttpServletRequest request) {
  return request.getParameter(usernameParameter);
 }

 // 参见上面对应的说明为凭据设置一些请求细节
 protected void setDetails(HttpServletRequest request,
   UsernamePasswordAuthenticationToken authRequest) {
  authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
 }

 // 设置账户参数的key
 public void setUsernameParameter(String usernameParameter) {
  Assert.hasText(usernameParameter, "Username parameter must not be empty or null");
  this.usernameParameter = usernameParameter;
 }

 // 设置密码参数的key
 public void setPasswordParameter(String passwordParameter) {
  Assert.hasText(passwordParameter, "Password parameter must not be empty or null");
  this.passwordParameter = passwordParameter;
 }

 // 认证的请求方式是只支持POST请求
 public void setPostOnly(boolean postOnly) {
  this.postOnly = postOnly;
 }

 public final String getUsernameParameter() {
  return usernameParameter;
 }

 public final String getPasswordParameter() {
  return passwordParameter;
 }
}

为了加强对流程的理解,我特意画了一张图来对这个流程进行清晰的说明:

3. 我们可以定制什么

根据上面的流程,我们理解了UsernamePasswordAuthenticationFilter工作流程后可以做这些事情:

定制我们的登录请求URI和请求方式。

登录请求参数的格式定制化,比如可以使用JSON格式提交甚至几种并存。

如何将用户名和密码封装入凭据UsernamePasswordAuthenticationToken,定制业务场景需要的特殊凭据。

4. 我们会有什么疑问

AuthenticationManager从哪儿来,它又是什么,它是如何对凭据进行认证的,认证成功的后续细节是什么,认证失败的后续细节是什么。不要走开,持续关注:码农小胖哥 为你揭晓这个答案。

到此这篇关于图解Spring Security 中用户是如何实现登录的的文章就介绍到这了,更多相关Spring Security  用户 实现登录内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 微服务SpringBoot整合Jasypt加密工具的场景分析

    微服务SpringBoot整合Jasypt加密工具的场景分析

    Jasypt是Java加密工具包,能支持对密码的哈希加密,对文本和二进制数据的对称加解密,还能集成SpringBoot项目对配置文件中的密钥进行加密存储,这篇文章主要介绍了微服务SpringBoot整合Jasypt加密工具,需要的朋友可以参考下
    2022-10-10
  • Java中的延迟队列DelayQueue详细解析

    Java中的延迟队列DelayQueue详细解析

    这篇文章主要介绍了Java中的延迟队列DelayQueue详细解析,JDK自身支持延迟队列的数据结构,其实类:java.util.concurrent.DelayQueue,<BR>我们通过阅读源码的方式理解该延迟队列类的实现过程,需要的朋友可以参考下
    2023-12-12
  • java中添加按钮并添加响应事件的方法(推荐)

    java中添加按钮并添加响应事件的方法(推荐)

    下面小编就为大家带来一篇java中添加按钮并添加响应事件的方法(推荐)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-04-04
  • 基于Java 生产者消费者模式(详细分析)

    基于Java 生产者消费者模式(详细分析)

    下面小编就为大家分享一篇基于Java 生产者消费者模式(详细分析),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-01-01
  • java8 stream sort自定义复杂排序案例

    java8 stream sort自定义复杂排序案例

    这篇文章主要介绍了java8 stream sort自定义复杂排序案例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-10-10
  • Redis缓存及热点key问题解决方案

    Redis缓存及热点key问题解决方案

    这篇文章主要介绍了Redis缓存及热点key问题解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04
  • Springboot整合Gson报错问题解决过程

    Springboot整合Gson报错问题解决过程

    这篇文章主要介绍了Springboot整合Gson报错问题解决过程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-06-06
  • 解析阿里GTS开源版本fescar分布式事务

    解析阿里GTS开源版本fescar分布式事务

    这篇文章主要为大家介绍解析阿里GTS开源版本fescar分布式事务的原理及使用说明,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多进步
    2022-02-02
  • Java中迭代器Iterator的使用解析

    Java中迭代器Iterator的使用解析

    Java采用了迭代器来为各种容器提供了公共的操作接口,下面通过本文给大家分享Java中迭代器Iterator的使用解析,需要的朋友参考下吧
    2017-09-09
  • Spring Security实现HTTP认证

    Spring Security实现HTTP认证

    本文主要介绍了Spring Security实现HTTP认证,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧<BR>
    2022-06-06

最新评论