千家信息网

Spring Security的登陆流程是什么

发表于:2025-11-09 作者:千家信息网编辑
千家信息网最后更新 2025年11月09日,本篇内容介绍了"Spring Security的登陆流程是什么"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学
千家信息网最后更新 2025年11月09日Spring Security的登陆流程是什么

本篇内容介绍了"Spring Security的登陆流程是什么"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

在Spring Security中,认证授权都是通过过滤器来实现的。

当开始登陆的时候,有一个关键的过滤器UsernamePasswordAuthenticationFilter,该类继承抽象类AbstractAuthenticationProcessingFilter,在AbstractAuthenticationProcessingFilter里有一个doFilter方法,一切先从这里说起。

private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)      throws IOException, ServletException {   if (!requiresAuthentication(request, response)) {      chain.doFilter(request, response);      return;   }   try {      Authentication authenticationResult = attemptAuthentication(request, response);      if (authenticationResult == null) {         // return immediately as subclass has indicated that it hasn't completed         return;      }      this.sessionStrategy.onAuthentication(authenticationResult, request, response);      // Authentication success      if (this.continueChainBeforeSuccessfulAuthentication) {         chain.doFilter(request, response);      }      successfulAuthentication(request, response, chain, authenticationResult);   }   catch (InternalAuthenticationServiceException failed) {      this.logger.error("An internal error occurred while trying to authenticate the user.", failed);      unsuccessfulAuthentication(request, response, failed);   }   catch (AuthenticationException ex) {      // Authentication failed      unsuccessfulAuthentication(request, response, ex);   }}

首先requiresAuthentication先判断是否尝试校验,通过后调用attemptAuthentication方法,这个方法也就是UsernamePasswordAuthenticationFilter 中的attemptAuthentication方法。

public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)      throws AuthenticationException {   if (this.postOnly && !request.getMethod().equals("POST")) {      throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());   }   String username = obtainUsername(request);   username = (username != null) ? username : "";   username = username.trim();   String password = obtainPassword(request);   password = (password != null) ? password : "";   UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);   // Allow subclasses to set the "details" property   setDetails(request, authRequest);   return this.getAuthenticationManager().authenticate(authRequest);}

1.在UsernamePasswordAuthenticationFilter 的attemptAuthentication方法中,先是验证请求的类型,是否是POST请求,如果不是的话,抛出异常。(PS:登陆肯定要用POST方法了)
2.然后拿到username和password。这里使用的是obtainUsername方法,也就是get方法。

@Nullableprotected String obtainPassword(HttpServletRequest request) {   return request.getParameter(this.passwordParameter);}@Nullableprotected String obtainUsername(HttpServletRequest request) {   return request.getParameter(this.usernameParameter);}

由此我们知道了Spring Security中是通过get方法来拿到参数,所以在进行前后端分离的时候是无法接受JSON数据,处理方法就是自定义一个Filter来继承UsernamePasswordAuthenticationFilter,重写attemptAuthentication方法,然后创建一个Filter实例写好登陆成功和失败的逻辑处理,在HttpSecurity参数的configure中通过addFilterAt来替换Spring Security官方提供的过滤器。
3.创建一个UsernamePasswordAuthenticationToken 实例。
4.设置Details,在这里关键的是在WebAuthenticationDetails类中记录了用户的remoteAddress和sessionId。

public WebAuthenticationDetails(HttpServletRequest request) {   this.remoteAddress = request.getRemoteAddr();   HttpSession session = request.getSession(false);   this.sessionId = (session != null) ? session.getId() : null;}

5.拿到一个AuthenticationManager通过authenticate方法进行校验,这里以实现类ProviderManager为例。

@Overridepublic Authentication authenticate(Authentication authentication) throws AuthenticationException {   //获取Authentication的运行时类   Class toTest = authentication.getClass();   AuthenticationException lastException = null;   AuthenticationException parentException = null;   Authentication result = null;   Authentication parentResult = null;   int currentPosition = 0;   int size = this.providers.size();      for (AuthenticationProvider provider : getProviders()) {       //判断是否支持处理该类别的provider      if (!provider.supports(toTest)) {         continue;      }      if (logger.isTraceEnabled()) {         logger.trace(LogMessage.format("Authenticating request with %s (%d/%d)",               provider.getClass().getSimpleName(), ++currentPosition, size));      }      try {          //获取用户的信息         result = provider.authenticate(authentication);         if (result != null) {            copyDetails(authentication, result);            break;         }      }      catch (AccountStatusException | InternalAuthenticationServiceException ex) {         prepareException(ex, authentication);         // SEC-546: Avoid polling additional providers if auth failure is due to         // invalid account status         throw ex;      }      catch (AuthenticationException ex) {         lastException = ex;      }   }   //不支持的话跳出循环再次执行   if (result == null && this.parent != null) {      // Allow the parent to try.      try {         parentResult = this.parent.authenticate(authentication);         result = parentResult;      }      catch (ProviderNotFoundException ex) {         // ignore as we will throw below if no other exception occurred prior to         // calling parent and the parent         // may throw ProviderNotFound even though a provider in the child already         // handled the request      }      catch (AuthenticationException ex) {         parentException = ex;         lastException = ex;      }   }   if (result != null) {       //擦除用户的凭证 也就是密码      if (this.eraseCredentialsAfterAuthentication && (result instanceof CredentialsContainer)) {         // Authentication is complete. Remove credentials and other secret data         // from authentication         ((CredentialsContainer) result).eraseCredentials();      }      // If the parent AuthenticationManager was attempted and successful then it      // will publish an AuthenticationSuccessEvent      // This check prevents a duplicate AuthenticationSuccessEvent if the parent      // AuthenticationManager already published it      if (parentResult == null) {          //公示登陆成功         this.eventPublisher.publishAuthenticationSuccess(result);      }      return result;   }   // Parent was null, or didn't authenticate (or throw an exception).   if (lastException == null) {      lastException = new ProviderNotFoundException(this.messages.getMessage("ProviderManager.providerNotFound",            new Object[] { toTest.getName() }, "No AuthenticationProvider found for {0}"));   }   // If the parent AuthenticationManager was attempted and failed then it will   // publish an AbstractAuthenticationFailureEvent   // This check prevents a duplicate AbstractAuthenticationFailureEvent if the   // parent AuthenticationManager already published it   if (parentException == null) {      prepareException(lastException, authentication);   }   throw lastException;}

6.经过一系列校验,此时登陆校验基本完成,当验证通过后会执行doFilter中的successfulAuthentication方法,跳转到我们设置的登陆成功界面,验证失败会执行unsuccessfulAuthentication方法,跳转到我们设置的登陆失败界面。

"Spring Security的登陆流程是什么"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

方法 登陆 成功 也就是 用户 过滤器 处理 验证 流程 关键 内容 参数 实例 时候 更多 界面 知识 支持 实用 学有所成 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 设置数据库访问密码 查询数据库所在盘符空间 全国青少年女足注册数据库 计算机网络安全教师教学随笔 服务器虚拟机管理程序 成都卡社诺网络技术有限公司 数据库连接游标 戴尔服务器磁盘阵列不引导 关于护苗网络安全知识课堂感悟 余姚应用软件开发平台 我的世界离线登录创建服务器 软件开发技术目标及内容 北京web前端软件开发价位 dnf登录不显示服务器怎么办 怎么查询数据库表字段为不为空 漯河网络安全普查 福建潮流软件开发设施价钱 网络安全专业缺人吗 ug数据库收藏 网络安全系统怎么关 服务器节点距离大 兴业银行 软件开发工程师 access数据库保存后打开 ibm服务器硬盘启动 江苏pdu服务器专用电源哪种好 河南服务器托管厂家云空间 软件开发技术目标及内容 北京路云天网络安全研究院 数据库原理及应用期末试题 为什么服务器没有响应进不去游戏
0