图解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  用户 实现登录内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java8中Optional的一些常见错误用法总结

    Java8中Optional的一些常见错误用法总结

    我们知道 Java 8 增加了一些很有用的 API, 其中一个就是 Optional,下面这篇文章主要给大家介绍了关于Java8中Optional的一些常见错误用法的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2018-07-07
  • springboot上传文件并返回url过程

    springboot上传文件并返回url过程

    这篇文章主要介绍了springboot上传文件并返回url过程,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • Spring注解方式防止重复提交原理详解

    Spring注解方式防止重复提交原理详解

    这篇文章主要为大家详细介绍了Spring注解方式防止重复提交原理,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-11-11
  • SpringCloud的Hystrix简单介绍

    SpringCloud的Hystrix简单介绍

    这篇文章主要介绍了SpringCloud的Hystrix简单介绍,SpringCloud Hystrix是Netflix开源的一款容错框架,具备服务降级,服务熔断,依赖隔离,监控(Hystrix Dashboard)等功能,同样具有自我保护能力,需要的朋友可以参考下
    2023-07-07
  • Java消息队列Kafka的简单概述

    Java消息队列Kafka的简单概述

    这篇文章主要介绍了Java消息队列Kafka的简单概述,消息系统负责将数据从一个应用程序传输到另一个应用程序,应用程序可以专注于数据,不担心如何共享它,需要的朋友可以参考下
    2023-07-07
  • Idea springboot如何实现批量启动微服务

    Idea springboot如何实现批量启动微服务

    这篇文章主要介绍了Idea springboot如何实现批量启动微服务,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-05-05
  • 浅谈java多线程wait,notify

    浅谈java多线程wait,notify

    这篇文章主要介绍了java多线程wait,notify,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,下面小编和大家一起来学习一下吧
    2019-05-05
  • Spring Boot请求处理之常用参数注解使用教程

    Spring Boot请求处理之常用参数注解使用教程

    这篇文章主要给大家介绍了关于Spring Boot请求处理之常用参数注解使用的相关资料,文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2022-03-03
  • 聊聊Spring Cloud Cli 初体验

    聊聊Spring Cloud Cli 初体验

    这篇文章主要介绍了聊聊Spring Cloud Cli 初体验,SpringBoot CLI 是spring Boot项目的脚手架工具。非常具有实用价值,需要的朋友可以参考下
    2018-04-04
  • Java程序命令行参数用法总结

    Java程序命令行参数用法总结

    这篇文章主要介绍了Java程序命令行参数用法总结,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09

最新评论