Spring Security 与 Spring MVC

一、核心架构:过滤器链 (Filter Chain)

Spring Security 的本质是一条 Servlet 过滤器链 (Filter Chain) 。它在请求到达 Spring MVC 的 DispatcherServlet 之前 就开始工作。

整体流程如下:

关键点 :Security 的所有工作都在 DispatcherServlet 之前完成。


二、Spring Security 认证 (Authentication) 详细过程

认证的目标是回答 "你是谁?" 的问题。

  1. 请求拦截:

    • 用户访问一个受保护的资源(例如 /api/user/profile)。
    • 请求首先被 DelegatingFilterProxy 拦截,并委托给 Spring Security 的 FilterChainProxy。
  2. 凭证提取:

    • 在你的自定义 JwtAuthenticationFilter (通常继承 OncePerRequestFilter) 中,从请求头(如 Authorization: Bearer <token>)中提取 JWT Token。
  3. 凭证验证:

    • 调用 JWT 工具类(如 jjwt 库)验证 Token 的签名、有效期等。
    • 如果 Token 无效、过期或缺失,不进行任何操作,直接放行到下一个 Filter。
  4. 身份构建:

    • 如果 Token 有效,从中解析出用户标识(如 username 或 userId)。
    • 调用 UserDetailsService.loadUserByUsername() 加载完整的用户信息和权限(UserDetails 对象)。
    • 基于这些信息,创建一个已认证的 Authentication 对象(通常是 UsernamePasswordAuthenticationToken)。
  5. 上下文存储:

    • 将这个 Authentication 对象存入 SecurityContext。
    • SecurityContextHolder.getContext().setAuthentication(authentication);
    • 这个上下文会在线程内共享,供后续的授权检查使用。
  6. 继续流程:

    • 请求继续沿着 Filter 链向下传递。

三、Spring Security 授权 (Authorization) 与 Spring MVC 的协作

授权的目标是回答 "你能做什么?" 的问题。

  1. 授权检查:

    • 在 Filter 链的末尾,FilterSecurityInterceptor 会根据你在 HttpSecurity 中配置的规则(如 .anyRequest().authenticated() 或 .requestMatchers("/admin/**").hasRole("ADMIN"))进行授权检查。
    • 它会检查 SecurityContext 中是否存在有效的 Authentication 对象及其权限。
  2. 决策点:

    • 情况 A:未通过认证/授权
      • 如果 SecurityContext 为空(未登录)或权限不足,ExceptionTranslationFilter 会捕获 AccessDeniedException 或 AuthenticationException。
      • 然后,它会调用你配置的 AuthenticationEntryPoint (处理 401) 或 AccessDeniedHandler (处理 403)。
      • 此时,请求根本不会到达 DispatcherServlet! 所以你看到的是 401,而不是 404。
    • 情况 B:通过认证/授权
      • 请求成功通过整个 Security Filter 链。
      • 请求终于到达 DispatcherServlet。
  3. Spring MVC 处理:

    • DispatcherServlet 开始工作,尝试根据 URL 找到匹配的 @Controller 和 @RequestMapping。
    • 如果找到:执行 Controller 逻辑,返回正常响应。
    • 如果找不到 :抛出 NoHandlerFoundException。
    • 这个异常会被你的 @ControllerAdvice 全局异常处理器 (GlobalExceptionHandler) 捕获,并格式化为 404 JSON 响应。

四、关键注意点与最佳实践

  1. 安全优先原则:

    • 永远不要为了"先看 404"而绕过 Security 。这会泄露 API 结构,带来严重安全风险。401 for unauthenticated 是正确且安全的行为。
  2. 明确划分公开/私有接口:

    • 在 HttpSecurity 配置中,清晰地使用 permitAll() 放行登录、注册、健康检查等公开接口。
    • 使用 authenticated() 或更细粒度的权限控制保护其他所有接口。
  3. 全局异常处理的职责分离:

    • Security 层异常 (AuthenticationException, AccessDeniedException):由 Security 自己的 EntryPoint 和 AccessDeniedHandler 处理,返回 401/403。
    • MVC 层异常 (NoHandlerFoundException, MethodArgumentNotValidException):由 @ControllerAdvice 处理,返回 404/400 等。
    • 业务层异常 :也由 @ControllerAdvice 处理。
  4. 无状态认证 (JWT) 的要点:

    • 不要使用 Session :确保 HttpSecurity 配置了 .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)。
    • 每次请求都验证 :在自定义 Filter 中,对每个请求都重新验证 Token 并重建 SecurityContext。
  5. CORS 与 CSRF:

    • 前后端分离项目:务必正确配置 CORS。
    • 无状态 API (JWT) :通常需要禁用 CSRF 保护,因为客户端无法安全地存储和发送 CSRF Token。.csrf().disable()。
  6. 密码安全:

    • 永远不要明文存储密码。必须使用 PasswordEncoder (如 BCryptPasswordEncoder) 进行加密。
  7. 测试策略:

    • 测试 404 时,务必使用有效的 Token。这是验证你的全局异常处理器是否工作的唯一正确方式。
相关推荐
wangchunyu1143 小时前
JAVA CompletableFuture异步编程实战
java·开发语言·python
paopaokaka_luck4 小时前
流浪动物救助与收养系统(DeepSeek AI对话、 ECharts多维分析、救助流程衔接、领养与回访衔接、 捐赠确认与公示、志愿者协作)
java·前端·javascript·人工智能·mysql·echarts·推荐算法
Thomas.Sir4 小时前
第9课:SpringBoot4.x Web开发基础:WebMvc自动配置、静态资源、请求参数接收
java·spring boot
程序 代码狂人4 小时前
切片表与分区表的区别(数据开发面试版)
java·大数据·开发语言·数据仓库·算法
2501_944521595 小时前
Deepmerge 跨端三方库仓颉适配全流程
java·python·eclipse·github
南归北隐6 小时前
Spring AI Alibaba Graph框架实现MCP数据库查询实战
java·后端·spring ai·mcp·spring ai mcp
古法老登瞎折腾6 小时前
大数据智能运维实战(九):让 AI 查日志——找到异常,也保留上下文
java·大数据·运维·人工智能·spring ai·mcp
ai大模型-探索者7 小时前
Function Call与MCP(区别、联系与实战)
java·服务器·网络
略略略咯咯7 小时前
啊啊啊啊啊
java·服务器·数据库
雷一言说7 小时前
Spring AI 2.0 Tool Search:工具多了,只把相关的发给模型
spring