Spring Security 认证流程——补充

news2025/7/26 18:43:44

一、认证流程概述

Spring Security 的认证流程基于 过滤器链(Filter Chain),核心组件包括 UsernamePasswordAuthenticationFilterAuthenticationManagerUserDetailsService 等。整个流程可分为以下步骤:

  1. 用户提交登录请求
  2. 拦截请求并封装认证对象
  3. 认证管理器(AuthenticationManager)处理认证
  4. 认证成功或失败的处理
  5. 安全上下文存储与后续处理

二、详细步骤解析

1. 用户提交登录请求

  • 用户通过表单提交用户名和密码(如访问 /login 路径)。
  • 请求由 UsernamePasswordAuthenticationFilter 拦截(默认处理 /login 请求)。

2. 拦截请求并封装认证对象

  • UsernamePasswordAuthenticationFilter 的作用
    • 从请求中提取用户名和密码。
    • 创建 UsernamePasswordAuthenticationToken 对象(未认证的 Authentication 实例)。
    • 示例代码:
public class UsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) {
        String username = obtainUsername(request); // 提取用户名
        String password = obtainPassword(request); // 提取密码
        UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
        return this.getAuthenticationManager().authenticate(authRequest); // 调用认证管理器
    }
}

3. 认证管理器(AuthenticationManager)处理认证

  • AuthenticationManager 的职责
    • 协调认证流程,调用 AuthenticationProvider 进行具体认证。
    • 默认实现是 ProviderManager,其内部维护一个 AuthenticationProvider 列表。
  • DaoAuthenticationProvider 的角色
    • 负责从数据源加载用户信息(通过 UserDetailsService)。
    • 对比用户输入的密码与数据库中存储的密码(通过 PasswordEncoder)。
    • 示例代码:
public class DaoAuthenticationProvider implements AuthenticationProvider {
    @Override
    public Authentication authenticate(Authentication authentication) {
        String username = authentication.getName();
        UserDetails userDetails = userDetailsService.loadUserByUsername(username); // 加载用户信息
        if (passwordEncoder.matches(authentication.getCredentials().toString(), userDetails.getPassword())) {
            return new UsernamePasswordAuthenticationToken(userDetails, authentication.getCredentials(), userDetails.getAuthorities());
        } else {
            throw new BadCredentialsException("密码错误");
        }
    }
}

4. 认证成功或失败的处理

  • 认证成功

    • AuthenticationManager 返回已认证的 Authentication 对象。
    • UsernamePasswordAuthenticationFilter 将该对象存入 SecurityContextHolder(通过 SecurityContext)。
    • 触发 AuthenticationSuccessHandler(如跳转到首页或返回 JWT 令牌)。
    • 示例代码:
public class UsernamePasswordAuthenticationFilter {
    private AuthenticationSuccessHandler successHandler;

    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, Authentication authResult) {
        SecurityContextHolder.getContext().setAuthentication(authResult); // 存储认证信息
        successHandler.onAuthenticationSuccess(request, response, authResult); // 调用成功处理器
    }
}

认证失败

  • AuthenticationManager 抛出 AuthenticationException 异常。
  • UsernamePasswordAuthenticationFilter 调用 AuthenticationFailureHandler(如返回错误信息或重定向到登录页面)。
  • 示例代码:
public class UsernamePasswordAuthenticationFilter {
    private AuthenticationFailureHandler failureHandler;

    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) {
        failureHandler.onAuthenticationFailure(request, response, failed); // 调用失败处理器
    }
}

5. 安全上下文存储与后续处理

  • SecurityContextPersistenceFilter 的作用
    • 在请求开始时,从 SecurityContextRepository(默认是 HttpSessionSecurityContextRepository)加载 SecurityContext 到当前线程。
    • 在请求结束时,将 SecurityContext 保存回 SecurityContextRepository 并清空线程中的上下文。
    • 示例代码:
public class SecurityContextPersistenceFilter implements Filter {
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpSession session = request.getSession(false);
        SecurityContext context = session != null ? (SecurityContext) session.getAttribute("SPRING_SECURITY_CONTEXT") : null;
        SecurityContextHolder.setContext(context); // 加载上下文
        try {
            chain.doFilter(req, res);
        } finally {
            session = ((HttpServletRequest) req).getSession(false);
            session.setAttribute("SPRING_SECURITY_CONTEXT", SecurityContextHolder.getContext()); // 保存上下文
            SecurityContextHolder.clearContext(); // 清空线程上下文
        }
    }
}

三、关键组件与接口

组件/接口职责
Authentication封装用户凭证(如用户名、密码)和权限信息。
AuthenticationManager认证入口,协调多个 AuthenticationProvider
AuthenticationProvider具体认证逻辑的实现者(如 DaoAuthenticationProvider)。
UserDetailsService从数据源加载用户信息(如数据库),返回 UserDetails 对象。
PasswordEncoder加密和校验密码(如 BCryptPasswordEncoder)。
SecurityContext存储当前用户的认证信息(通过 SecurityContextHolder 与线程绑定)。

四、认证流程图

[用户提交登录请求]
       ↓
[UsernamePasswordAuthenticationFilter 拦截请求]
       ↓
[创建 UsernamePasswordAuthenticationToken(未认证)]
       ↓
[调用 AuthenticationManager.authenticate()]
       ↓
[ProviderManager 遍历 AuthenticationProvider]
       ↓
[DaoAuthenticationProvider 加载用户信息(通过 UserDetailsService)]
       ↓
[PasswordEncoder 校验密码]
       ↓
[认证成功:返回已认证的 Authentication 对象]
       ↓
[SecurityContextHolder 存储 Authentication]
       ↓
[调用 AuthenticationSuccessHandler(如跳转页面或返回 JWT)]

五、自定义认证逻辑

  • 自定义 UserDetailsService

    • 实现 UserDetailsService 接口,从数据库加载用户信息。
    • 示例代码:
@Service
public class CustomUserDetailsService implements UserDetailsService {
    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("用户不存在");
        }
        return new org.springframework.security.core.userdetails.User(
            user.getUsername(),
            user.getPassword(),
            AuthorityUtils.createAuthorityList("ROLE_USER") // 返回用户权限
        );
    }
}

自定义 PasswordEncoder

  • 使用 BCryptPasswordEncoder 或自定义加密逻辑。
  • 示例代码:
@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

六、常见问题与解决方案

  • 密码不匹配

    • 确保 UserDetailsService 返回的密码与数据库中存储的密码格式一致(如已加密)。
    • 检查 PasswordEncoder 配置是否正确。
  • 认证失败无提示

    • 自定义 AuthenticationFailureHandler 处理异常,返回用户友好的错误信息。
  • 多认证方式支持

    • 添加自定义过滤器(如 JWT 认证过滤器),插入到过滤器链中。
    • 示例配置:
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilterBefore(new JwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
    }
}

七、总结

Spring Security 的认证流程通过 过滤器链核心组件协作 实现,关键步骤包括:

  1. 用户提交登录请求,被 UsernamePasswordAuthenticationFilter 拦截。
  2. AuthenticationManager 协调 AuthenticationProvider 进行认证。
  3. UserDetailsService 加载用户信息,PasswordEncoder 校验密码。
  4. 认证结果通过 SecurityContext 存储,并触发成功或失败处理器。

掌握这一流程后,开发者可以灵活配置认证逻辑(如数据库认证、JWT 认证)并扩展安全功能(如动态权限控制)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2406994.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散

前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说,在叠衣服的过程中,我会带着团队对比各种模型、方法、策略,毕竟针对各个场景始终寻找更优的解决方案,是我个人和我司「七月在线」的职责之一 且个人认为&#xff0c…

协议转换利器,profinet转ethercat网关的两大派系,各有千秋

随着工业以太网的发展,其高效、便捷、协议开放、易于冗余等诸多优点,被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口,具有实时性、开放性,使用TCP/IP和IT标准,符合基于工业以太网的…

9-Oracle 23 ai Vector Search 特性 知识准备

很多小伙伴是不是参加了 免费认证课程(限时至2025/5/15) Oracle AI Vector Search 1Z0-184-25考试,都顺利拿到certified了没。 各行各业的AI 大模型的到来,传统的数据库中的SQL还能不能打,结构化和非结构的话数据如何和…

mac:大模型系列测试

0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何,是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试,是可以跑通文章里面的代码。训练速度也是很快的。 注意…

DBLP数据库是什么?

DBLP(Digital Bibliography & Library Project)Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高,数据库文献更新速度很快,很好地反映了国际计算机科学学术研…

Xela矩阵三轴触觉传感器的工作原理解析与应用场景

Xela矩阵三轴触觉传感器通过先进技术模拟人类触觉感知,帮助设备实现精确的力测量与位移监测。其核心功能基于磁性三维力测量与空间位移测量,能够捕捉多维触觉信息。该传感器的设计不仅提升了触觉感知的精度,还为机器人、医疗设备和制造业的智…

DeepSeek源码深度解析 × 华为仓颉语言编程精粹——从MoE架构到全场景开发生态

前言 在人工智能技术飞速发展的今天,深度学习与大模型技术已成为推动行业变革的核心驱动力,而高效、灵活的开发工具与编程语言则为技术创新提供了重要支撑。本书以两大前沿技术领域为核心,系统性地呈现了两部深度技术著作的精华:…

stm32wle5 lpuart DMA数据不接收

配置波特率9600时,需要使用外部低速晶振

Unity中的transform.up

2025年6月8日,周日下午 在Unity中,transform.up是Transform组件的一个属性,表示游戏对象在世界空间中的“上”方向(Y轴正方向),且会随对象旋转动态变化。以下是关键点解析: 基本定义 transfor…

Elastic 获得 AWS 教育 ISV 合作伙伴资质,进一步增强教育解决方案产品组合

作者:来自 Elastic Udayasimha Theepireddy (Uday), Brian Bergholm, Marianna Jonsdottir 通过搜索 AI 和云创新推动教育领域的数字化转型。 我们非常高兴地宣布,Elastic 已获得 AWS 教育 ISV 合作伙伴资质。这一重要认证表明,Elastic 作为 …

MySQL的pymysql操作

本章是MySQL的最后一章,MySQL到此完结,下一站Hadoop!!! 这章很简单,完整代码在最后,详细讲解之前python课程里面也有,感兴趣的可以往前找一下 一、查询操作 我们需要打开pycharm …

渗透实战PortSwigger靶场:lab13存储型DOM XSS详解

进来是需要留言的&#xff0c;先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码&#xff0c;输入的<>当成字符串处理回显到页面中&#xff0c;看来只是把用户输…

[论文阅读]TrustRAG: Enhancing Robustness and Trustworthiness in RAG

TrustRAG: Enhancing Robustness and Trustworthiness in RAG [2501.00879] TrustRAG: Enhancing Robustness and Trustworthiness in Retrieval-Augmented Generation 代码&#xff1a;HuichiZhou/TrustRAG: Code for "TrustRAG: Enhancing Robustness and Trustworthin…

水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关

在水泥厂的生产流程中&#xff0c;工业自动化网关起着至关重要的作用&#xff0c;尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关&#xff0c;为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多&#xff0c;其中不少设备采用Devicenet协议。Devicen…

Linux中《基础IO》详细介绍

目录 理解"文件"狭义理解广义理解文件操作的归类认知系统角度文件类别 回顾C文件接口打开文件写文件读文件稍作修改&#xff0c;实现简单cat命令 输出信息到显示器&#xff0c;你有哪些方法stdin & stdout & stderr打开文件的方式 系统⽂件I/O⼀种传递标志位…

【Veristand】Veristand环境安装教程-Linux RT / Windows

首先声明&#xff0c;此教程是针对Simulink编译模型并导入Veristand中编写的&#xff0c;同时需要注意的是老用户编译可能用的是Veristand Model Framework&#xff0c;那个是历史版本&#xff0c;且NI不会再维护&#xff0c;新版本编译支持为VeriStand Model Generation Suppo…

Ubuntu系统多网卡多相机IP设置方法

目录 1、硬件情况 2、如何设置网卡和相机IP 2.1 万兆网卡连接交换机&#xff0c;交换机再连相机 2.1.1 网卡设置 2.1.2 相机设置 2.3 万兆网卡直连相机 1、硬件情况 2个网卡n个相机 电脑系统信息&#xff0c;系统版本&#xff1a;Ubuntu22.04.5 LTS&#xff1b;内核版本…

《Docker》架构

文章目录 架构模式单机架构应用数据分离架构应用服务器集群架构读写分离/主从分离架构冷热分离架构垂直分库架构微服务架构容器编排架构什么是容器&#xff0c;docker&#xff0c;镜像&#xff0c;k8s 架构模式 单机架构 单机架构其实就是应用服务器和单机服务器都部署在同一…

ubuntu22.04有线网络无法连接,图标也没了

今天突然无法有线网络无法连接任何设备&#xff0c;并且图标都没了 错误案例 往上一顿搜索&#xff0c;试了很多博客都不行&#xff0c;比如 Ubuntu22.04右上角网络图标消失 最后解决的办法 下载网卡驱动&#xff0c;重新安装 操作步骤 查看自己网卡的型号 lspci | gre…

【堆垛策略】设计方法

堆垛策略的设计是积木堆叠系统的核心&#xff0c;直接影响堆叠的稳定性、效率和容错能力。以下是分层次的堆垛策略设计方法&#xff0c;涵盖基础规则、优化算法和容错机制&#xff1a; 1. 基础堆垛规则 (1) 物理稳定性优先 重心原则&#xff1a; 大尺寸/重量积木在下&#xf…