Spring Security的作用

news2025/3/13 22:07:22

一、概述

Spring Security是一个框架,提供认证(authentication)、授权(authorization)和保护,以抵御常见攻击。对 常见漏洞 的保护提供了全面的支持,它对保护命令式和响应式应用程序有一流的支持,是保护基于Spring的应用程序的事实标准。

二、各模块的作用

1、Core  spring-security-core.jar,该模块包含核心认证和访问控制类和接口、远程支持和基本配置API。任何使用 Spring Security 的应用程序都需要它。它支持独立的应用程序、远程客户端、方法(服务层)安全(Method security)和JDBC用户配置。它包含以下顶级包。

  • org.springframework.security.core

  • org.springframework.security.access

  • org.springframework.security.authentication

  • org.springframework.security.provisioning

2、Web  spring-security-web.jar,该模块包含过滤器和相关的web安全基础设施代码。它包含任何有servlet API依赖的东西。如果你需要Spring Security Web 认证服务和基于URL的访问控制,你就需要它。主包是 org.springframework.security.web

3、Config  spring-security-config.jar,该模块包含 security 命名空间解析代码和Java配置代码。如果你使用 Spring Security 的XML命名空间进行配置或 Spring Security 的 Java 配置支持,你就需要它。主包是 org.springframework.security.config

4、LDAP spring-security-ldap.jar,这个模块提供LDAP认证和供应代码。如果你需要使用LDAP认证或管理LDAP用户条目,就需要它。顶层包是 org.springframework.security.ldap

5、OAuth 2.0 Core  spring-security-oauth2-core.jar,包含核心类和接口,提供对 OAuth 2.0 授权框架和 OpenID Connect Core 1.0 的支持。使用OAuth 2.0或 OpenID Connect Core 1.0 的应用程序都需要它,如客户端、资源服务器和授权服务器。顶层包是 org.springframework.security.oauth2.core

6、OAuth 2.0 Client  spring-security-oauth2-client.jar,包含 Spring Security 对 OAuth 2.0 授权框架和 OpenID Connect Core 1.0 的客户端支持。使用 OAuth 2.0 或 OpenID Connect Core 1.0 的应用程序都需要它,如客户端、资源服务器和授权服务器。顶层包是 org.springframework.security.oauth2.core

7、OAuth 2.0 JOSE  spring-security-oauth2-jose.jar,包 含Spring Security 对 JOSE(Javascript Object Signing and Encryption)框架的支持。JOSE框架旨在提供一种方法,在各方之间安全地转移 claim。它是由一系列规范构建的。

  • JSON Web Token (JWT)

  • JSON Web Signature (JWS)

  • JSON Web Encryption (JWE)

  • JSON Web Key (JWK)                                                                                                               

  • 它包含以下顶级包。

  • org.springframework.security.oauth2.jwt

  • org.springframework.security.oauth2.jose

8、OAuth 2.0 Resource Server  spring-security-oauth2-resource-server.jar,包含 Spring Security 对 OAuth 2.0 资源服务器的支持。它用于通过使用 OAuth 2.0 Bearer Token 来保护API。顶层包是 org.springframework.security.oauth2.server.resource

9、ACL  spring-security-acl.jar,包含一个专门的 domain object ACL 实现。它用于在你的应用程序中对特定的 domain object 实例应用安全。顶层包是 org.springframework.security.acls

10、CAS — spring-security-cas.jar,包含 Spring Security 的 CAS 客户端集成。如果你想在CAS单点登录服务器上使用 Spring Security Web 认证,你应该使用它。顶层包是 org.springframework.security.cas

11、Test  spring-security-test.jar,包含对Spring Security测试的支持。

12、Taglib  spring-security-taglibs.jar,提供 Spring Security 的 JSP 标签实现。

13、Remoting  spring-security-remoting.jar,提供了与 Spring Remoting 的集成。 除非你正在编写一个使用 Spring Remoting 的远程客户端,否则你不需要这个。 主包是 org.springframework.security.remoting

三、Spring Security 并发支持类概述

Spring Security 提供了一系列并发支持类,用于在多线程环境中传递和管理 SecurityContext。这些类与 Java 并发 API 和 Spring 任务抽象无缝集成,能够确保异步任务或线程池任务在正确的安全上下文中执行。以下是主要的并发支持类及其功能:


1. DelegatingSecurityContextCallable
  • 用于包装 Callable 任务,在执行任务前设置 SecurityContext,并在任务完成后清理上下文。
  • 适用于需要返回值的异步任务。
2. DelegatingSecurityContextExecutor
  • 包装 Executor,在执行 Runnable 任务时自动传递 SecurityContext
  • 适用于线程池任务。
3. DelegatingSecurityContextExecutorService
  • 包装 ExecutorService,支持更复杂的任务管理(如 Future 和 Callable)。
  • 适用于需要任务提交和结果获取的场景。
4. DelegatingSecurityContextRunnable
  • 包装 Runnable 任务,在执行任务前设置 SecurityContext,并在任务完成后清理上下文。
  • 适用于简单的异步任务。
5. DelegatingSecurityContextScheduledExecutorService
  • 包装 ScheduledExecutorService,支持定时任务的 SecurityContext 传递。
  • 适用于需要周期性或延迟执行的任务。
6. DelegatingSecurityContextSchedulingTaskExecutor
  • 包装 Spring 的 SchedulingTaskExecutor,结合 Spring 任务抽象和 SecurityContext 传递。
  • 适用于 Spring 调度任务。
7. DelegatingSecurityContextAsyncTaskExecutor
  • 包装 Spring 的 AsyncTaskExecutor,支持异步任务的 SecurityContext 传递。
  • 适用于 Spring 异步任务。
8. DelegatingSecurityContextTaskExecutor
  • 包装 Spring 的 TaskExecutor,结合 Spring 任务抽象和 SecurityContext 传递。
  • 适用于 Spring 任务执行器。
9. DelegatingSecurityContextTaskScheduler
  • 包装 Spring 的 TaskScheduler,支持调度任务的 SecurityContext 传递。
  • 适用于 Spring 调度任务。

Spring Security 模块的 Jackson 支持

Spring Security 提供了多个模块的 Jackson 支持,用于序列化和反序列化与安全相关的类。这些模块可以显著简化分布式会话、缓存和跨服务通信中的数据处理。以下是提供 Jackson 支持的 Spring Security 模块及其对应的 Jackson 模块:


1. spring-security-core
  • 模块名称CoreJackson2Module
  • 功能: 提供对 Spring Security 核心类(如 SecurityContextAuthentication 等)的 Jackson 支持。

2. spring-security-web
  • 模块名称:
    • WebJackson2Module
    • WebServletJackson2Module
    • WebServerJackson2Module
  • 功能: 提供对 Web 相关类(如 SecurityContextHolderWebAuthenticationDetails 等)的 Jackson 支持,适用于 Servlet 和 WebFlux 环境。

3. spring-security-oauth2-client
  • 模块名称OAuth2ClientJackson2Module
  • 功能: 提供对 OAuth2 客户端相关类(如 OAuth2AuthorizedClientOAuth2User 等)的 Jackson 支持。

4. spring-security-cas
  • 模块名称CasJackson2Module
  • 功能: 提供对 CAS(Central Authentication Service)相关类的 Jackson 支持。

5、如何使用这些模块
  1. 注册模块
    使用 ObjectMapper.registerModules() 方法注册所需的 Jackson 模块。例如:

    ObjectMapper objectMapper = new ObjectMapper(); objectMapper.registerModules(SecurityJackson2Modules.getModules(getClass().getClassLoader()));

  2. 序列化与反序列化
    注册模块后,ObjectMapper 可以自动处理 Spring Security 相关类的序列化和反序列化。


6、总结

Spring Security 的 Jackson 支持模块为处理安全相关类的序列化和反序列化提供了强大的工具。通过注册这些模块,开发者可以简化分布式系统中的数据处理,提高开发效率和系统性能。以下是模块的快速总结:

模块名称Jackson 模块功能
spring-security-coreCoreJackson2Module核心安全类的支持
spring-security-webWebJackson2Module 等Web 相关类的支持
spring-security-oauth2-clientOAuth2ClientJackson2ModuleOAuth2 客户端类的支持
spring-security-casCasJackson2ModuleCAS 认证相关类的支持

通过合理使用这些模块,开发者可以更轻松地处理 Spring Security 相关的数据序列化和反序列化任务。

Spring Security 过滤器实现认证的机制

Spring Security 通过一系列过滤器(Filters)来实现认证功能。这些过滤器组成了一个过滤器链(FilterChain),每个过滤器负责处理特定的认证逻辑。以下是实现认证的关键过滤器及其作用:


1. 核心过滤器
  1. UsernamePasswordAuthenticationFilter
    • 功能:处理基于表单的登录认证。
    • 流程
      • 从请求中提取用户名和密码。
      • 创建 UsernamePasswordAuthenticationToken 对象。
      • 调用 AuthenticationManager 进行认证。
    • 配置:通常与 /login 路径关联。
  2. BasicAuthenticationFilter
    • 功能:处理 HTTP 基本认证(Basic Authentication)。
    • 流程
      • 从请求头中提取 Authorization 信息。
      • 解码用户名和密码。
      • 创建 UsernamePasswordAuthenticationToken 对象。
      • 调用 AuthenticationManager 进行认证。
  3. BearerTokenAuthenticationFilter
    • 功能:处理基于令牌(如 JWT)的认证。
    • 流程
      • 从请求头中提取令牌(如 Authorization: Bearer <token>)。
      • 验证令牌的有效性。
      • 创建 Authentication 对象并设置到安全上下文中。
  4. AnonymousAuthenticationFilter
    • 功能:为未认证的请求分配匿名用户身份。
    • 流程
      • 如果当前用户未认证,创建一个 AnonymousAuthenticationToken 对象。
      • 将该对象设置到安全上下文中。
  5. ExceptionTranslationFilter
    • 功能:处理认证过程中抛出的异常(如 AuthenticationException)。
    • 流程
      • 捕获异常并转换为相应的 HTTP 响应(如重定向到登录页或返回 401 状态码)。

2. 认证流程
  1. 请求拦截
    过滤器链中的过滤器拦截请求,并根据请求类型(如表单登录、HTTP 基本认证、令牌认证等)选择相应的认证逻辑。

  2. 认证信息提取
    从请求中提取认证信息(如用户名、密码、令牌等)。

  3. 认证对象创建
    创建 Authentication 对象(如 UsernamePasswordAuthenticationToken)。

  4. 认证管理
    调用 AuthenticationManager 进行认证。AuthenticationManager 委托给 AuthenticationProvider 实现具体的认证逻辑(如查询数据库验证用户信息)。

  5. 安全上下文设置
    如果认证成功,将 Authentication 对象设置到 SecurityContextHolder 中,表示当前用户已认证。

  6. 异常处理
    如果认证失败,抛出 AuthenticationException,由 ExceptionTranslationFilter 处理。

  7. 认证流程图


3、总结

Spring Security 通过过滤器链实现认证功能,每个过滤器负责特定的认证逻辑。以下是核心要点:

过滤器功能
UsernamePasswordAuthenticationFilter处理表单登录认证。
BasicAuthenticationFilter处理 HTTP 基本认证。
BearerTokenAuthenticationFilter处理基于令牌的认证。
AnonymousAuthenticationFilter为未认证请求分配匿名身份。
ExceptionTranslationFilter处理认证异常。

通过过滤器链,Spring Security 实现了灵活且强大的认证机制,支持多种认证方式。

Spring Security 高层架构

Spring Security 的高层架构主要基于 Servlet 过滤器(Filters),在基于 Servlet 的应用中,过滤器是处理 HTTP 请求的核心组件。以下是对其架构的详细解析:


1. 过滤器的作用

在 Servlet 容器中,过滤器用于处理 HTTP 请求和响应。Spring Security 利用过滤器实现认证、授权和防护功能。以下是过滤器的关键作用:

  • 拦截请求
    过滤器可以阻止后续过滤器或 Servlet 的执行,通常用于直接返回响应。
  • 修改请求或响应
    过滤器可以修改传递给后续过滤器或 Servlet 的 HttpServletRequest 或 HttpServletResponse
  • 过滤器链(FilterChain)
    过滤器的核心在于 FilterChain,它决定了过滤器的执行顺序和流程。

2. 过滤器链(FilterChain)

当客户端发送请求时,Servlet 容器会创建一个 FilterChain,包含所有需要处理该请求的过滤器和 Servlet。以下是关键点:

  • 执行顺序
    过滤器的执行顺序非常重要,因为每个过滤器只能影响后续的过滤器和 Servlet。
  • Spring MVC 中的 Servlet
    在 Spring MVC 应用中,DispatcherServlet 是处理请求的核心 Servlet。
  • 唯一性
    每个请求只能由一个 Servlet 处理,但可以由多个过滤器处理。

3. 过滤器的使用示例

以下是过滤器的典型实现:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
    // 在应用程序处理之前执行操作
    chain.doFilter(request, response);
    // 调用应用程序的其余部分
    // 在应用程序处理之后执行操作
}
  • chain.doFilter()
    调用该方法会继续执行后续的过滤器或 Servlet。
  • 前后操作
    过滤器可以在调用 chain.doFilter() 之前和之后执行自定义逻辑。

4、总结

Spring Security 的高层架构基于 Servlet 过滤器,通过过滤器链实现认证、授权和防护功能。以下是核心要点:

要点说明
过滤器的作用拦截请求、修改请求或响应,控制执行流程。
过滤器链决定过滤器的执行顺序,支持多个过滤器。
执行顺序过滤器的顺序至关重要,影响后续处理逻辑。

通过理解过滤器的工作原理,开发者可以更好地掌握 Spring Security 的架构和实现机制。

DelegatingFilterProxy 的作用与机制

DelegatingFilterProxy 是 Spring 提供的一个过滤器实现,用于桥接 Servlet 容器的生命周期和 Spring 的 ApplicationContext。以下是其核心功能与工作机制:


1. 功能概述
  • 桥接 Servlet 容器与 Spring
    DelegatingFilterProxy 允许在 Servlet 容器中注册过滤器,同时将过滤器的实际工作委托给 Spring 容器中的 Bean。
  • 延迟加载过滤器 Bean
    它支持延迟加载过滤器 Bean 实例,解决了 Servlet 容器启动时 Spring Bean 尚未加载的问题。

2. 工作机制
  1. 注册与委托

    • DelegatingFilterProxy 通过 Servlet 容器的标准机制注册。
    • 它将所有工作委托给 Spring 容器中实现了 Filter 接口的 Bean。
  2. 伪代码示例
    以下是 DelegatingFilterProxy 的伪代码实现:

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {                     
        // 延迟获取注册为 Spring Bean 的过滤器 
        Filter delegate = getFilterBean(someBeanName); 
        // 将工作委托给 Spring Bean 
        delegate.doFilter(request, response, chain); 
    }

  3. 延迟加载的优势

    • Servlet 容器需要在启动前注册过滤器实例。
    • Spring 通常使用 ContextLoaderListener 加载 Spring Bean,这发生在过滤器注册之后。
    • DelegatingFilterProxy 通过延迟加载机制解决了这一时序问题。

3. 应用场景
  • Spring Security 集成
    在 Spring Security 中,DelegatingFilterProxy 用于将安全过滤器链委托给 Spring 容器中的 Bean。
  • 自定义过滤器
    开发者可以将自定义过滤器注册为 Spring Bean,并通过 DelegatingFilterProxy 集成到 Servlet 容器中。

4、总结

DelegatingFilterProxy 是 Spring 中用于桥接 Servlet 容器和 Spring 容器的关键组件,其核心功能与工作机制如下:

功能说明
桥接机制将 Servlet 容器的过滤器委托给 Spring Bean。
延迟加载支持延迟加载过滤器 Bean,解决时序问题。
应用场景用于 Spring Security 集成和自定义过滤器。

通过 DelegatingFilterProxy,开发者可以更灵活地将 Spring Bean 集成到 Servlet 容器的过滤器链中。

FilterChainProxy 的作用与机制

FilterChainProxy 是 Spring Security 的核心组件之一,用于管理多个 SecurityFilterChain,并将请求委托给适当的过滤器链处理。以下是其核心功能与工作机制:


1. 功能概述
  • 过滤器链管理
    FilterChainProxy 负责管理多个 SecurityFilterChain,并根据请求的路径或其他条件选择合适的过滤器链。
  • 请求委托
    它将请求委托给匹配的 SecurityFilterChain,由该过滤器链中的过滤器处理请求。

2. 工作机制
  1. 过滤器链选择
    • FilterChainProxy 根据请求的路径或其他条件选择合适的 SecurityFilterChain
    • 每个 SecurityFilterChain 包含一组 Spring Security 过滤器。
  2. 请求处理
    • 如果请求匹配某个 SecurityFilterChainFilterChainProxy 会依次调用该过滤器链中的过滤器。
    • 过滤器链中的过滤器可以执行认证、授权、防护等操作。
  3. 与 DelegatingFilterProxy 的集成
    • FilterChainProxy 是一个 Spring Bean,通常通过 DelegatingFilterProxy 集成到 Servlet 容器中。
    • DelegatingFilterProxy 将 Servlet 容器的过滤器调用委托给 FilterChainProxy

3. 应用场景
  • 多路径安全配置
    例如,为 /admin/** 和 /user/** 分别配置不同的 SecurityFilterChain,实现不同的安全策略。
  • 动态安全逻辑
    根据请求的上下文(如用户角色、请求参数)动态选择过滤器链。
  • 统一管理
    通过 FilterChainProxy 统一管理所有 Spring Security 过滤器,简化配置和维护。

4、总结

FilterChainProxy 是 Spring Security 中用于管理过滤器链的核心组件,其核心功能与工作机制如下:

功能说明
过滤器链管理管理多个 SecurityFilterChain,根据请求选择合适的过滤器链。
请求委托将请求委托给匹配的 SecurityFilterChain,由其中的过滤器处理。
集成机制通过 DelegatingFilterProxy 集成到 Servlet 容器中。

通过 FilterChainProxy,Spring Security 实现了灵活且强大的过滤器链管理机制,支持多路径安全配置和动态安全逻辑。

SecurityFilterChain 的作用与机制

SecurityFilterChain 是 Spring Security 的核心组件之一,用于定义哪些 Spring Security 过滤器(Filters)应该被调用来处理特定的请求。它由 FilterChainProxy 使用,根据请求的路径或其他条件选择合适的过滤器链。


1. 功能概述
  • 过滤器链管理
    SecurityFilterChain 负责管理一组 Spring Security 过滤器,并根据请求的路径或其他条件决定是否调用这些过滤器。
  • 请求匹配
    每个 SecurityFilterChain 可以配置特定的请求匹配规则(如 URL 模式),只有匹配的请求才会被该过滤器链处理。

2. 工作机制
  1. 过滤器链选择
    • FilterChainProxy 根据请求的路径或其他条件选择合适的 SecurityFilterChain
    • 每个 SecurityFilterChain 包含一组 Spring Security 过滤器。
  2. 过滤器执行
    • 如果请求匹配某个 SecurityFilterChainFilterChainProxy 会依次调用该过滤器链中的过滤器。
    • 过滤器链中的过滤器可以执行认证、授权、防护等操作。
  3. 默认与自定义配置
    • Spring Security 提供了默认的 SecurityFilterChain,处理常见的认证和授权需求。
    • 开发者可以自定义 SecurityFilterChain,实现更复杂的请求处理逻辑。

3. 应用场景
  • 路径匹配
    例如,为 /admin/** 路径配置一个单独的 SecurityFilterChain,要求管理员权限。
  • 多租户支持
    根据请求的域名或租户信息选择不同的 SecurityFilterChain
  • 自定义安全逻辑
    实现基于业务需求的自定义安全逻辑,如特定 IP 地址的访问控制。

4、总结

SecurityFilterChain 是 Spring Security 中用于管理过滤器链的核心组件,其核心功能与工作机制如下:

功能说明
过滤器链管理管理一组 Spring Security 过滤器。
请求匹配根据请求的路径或其他条件选择过滤器链。
应用场景用于路径匹配、多租户支持、自定义安全逻辑。

通过 SecurityFilterChain,开发者可以灵活地配置和管理 Spring Security 的过滤器链,满足不同的安全需求。

FilterChainProxy 和 SecurityFilterChain 的作用与优势

FilterChainProxy 是 Spring Security 的核心组件,用于管理多个 SecurityFilterChain,并根据请求的路径或其他条件选择合适的过滤器链。以下是其核心功能与优势:


1. FilterChainProxy 的核心功能
  1. 统一入口
    FilterChainProxy 是 Spring Security Servlet 支持的统一入口,所有请求都会经过它。
  2. 任务执行
    • 清理 SecurityContext,避免内存泄漏。
    • 应用 HttpFirewall,保护应用程序免受特定类型的攻击。
  3. 灵活调用
    通过 RequestMatcher 接口,FilterChainProxy 可以根据 HttpServletRequest 中的任何内容决定是否调用 SecurityFilterChain,而不仅仅依赖于 URL。

2. SecurityFilterChain 的配置与调用
  1. 多过滤器链支持
    FilterChainProxy 可以管理多个 SecurityFilterChain,每个过滤器链可以配置不同的安全规则。
  2. 匹配机制
    • 只有第一个匹配的 SecurityFilterChain 会被调用。
    • 例如,对于 URL /api/messages/,如果匹配 SecurityFilterChain0 的 /api/** 模式,则只会调用 SecurityFilterChain0,即使它也匹配其他过滤器链。
  3. 独立配置
    每个 SecurityFilterChain 可以独立配置,甚至可以配置为零个过滤器,以忽略某些请求。

3. 优势总结
优势说明
统一入口提供 Spring Security Servlet 支持的统一入口。
任务执行清理 SecurityContext,应用 HttpFirewall
灵活调用根据 HttpServletRequest 中的内容决定调用。
多过滤器链支持多个 SecurityFilterChain,独立配置。

4、总结

FilterChainProxy 和 SecurityFilterChain 是 Spring Security 中用于管理过滤器链的核心组件,提供了统一入口、任务执行、灵活调用和多过滤器链支持等优势。通过 FilterChainProxy,开发者可以灵活地配置和管理 Spring Security 的过滤器链,满足不同的安全需求。

Spring Security Filters 的作用与顺序

Spring Security Filters 是 Spring Security 的核心组件,用于处理认证、授权、防护等安全逻辑。这些过滤器通过 SecurityFilterChain API 插入到 FilterChainProxy 中,过滤器的顺序非常重要。以下是 Spring Security Filters 的完整列表及其作用:


1. 过滤器列表

以下是 Spring Security Filters 的完整列表,按执行顺序排列:

  1. ChannelProcessingFilter
    确保请求通过安全的通道(如 HTTPS)。

  2. WebAsyncManagerIntegrationFilter
    集成 Web 异步管理器。

  3. SecurityContextPersistenceFilter
    在请求之间持久化和恢复 SecurityContext

  4. HeaderWriterFilter
    向响应中添加安全相关的 HTTP 头。

  5. CorsFilter
    处理跨域资源共享(CORS)请求。

  6. CsrfFilter
    防护跨站请求伪造(CSRF)攻击。

  7. LogoutFilter
    处理用户注销请求。

  8. OAuth2AuthorizationRequestRedirectFilter
    处理 OAuth2 授权请求重定向。

  9. Saml2WebSsoAuthenticationRequestFilter
    处理 SAML2 Web SSO 认证请求。

  10. X509AuthenticationFilter
    基于 X.509 证书的认证。

  11. AbstractPreAuthenticatedProcessingFilter
    预认证处理的抽象基类。

  12. CasAuthenticationFilter
    处理 CAS 认证。

  13. OAuth2LoginAuthenticationFilter
    处理 OAuth2 登录认证。

  14. Saml2WebSsoAuthenticationFilter
    处理 SAML2 Web SSO 认证。

  15. UsernamePasswordAuthenticationFilter
    处理基于用户名和密码的认证。

  16. OpenIDAuthenticationFilter
    处理 OpenID 认证。

  17. DefaultLoginPageGeneratingFilter
    生成默认登录页面。

  18. DefaultLogoutPageGeneratingFilter
    生成默认注销页面。

  19. ConcurrentSessionFilter
    处理并发会话控制。

  20. DigestAuthenticationFilter
    处理摘要认证。

  21. BearerTokenAuthenticationFilter
    处理基于 Bearer Token 的认证。

  22. BasicAuthenticationFilter
    处理基本认证。

  23. RequestCacheAwareFilter
    缓存请求以便重定向后恢复。

  24. SecurityContextHolderAwareRequestFilter
    将 SecurityContext 绑定到请求。

  25. JaasApiIntegrationFilter
    集成 JAAS API。

  26. RememberMeAuthenticationFilter
    处理“记住我”功能。

  27. AnonymousAuthenticationFilter
    处理匿名用户认证。

  28. OAuth2AuthorizationCodeGrantFilter
    处理 OAuth2 授权码授予。

  29. SessionManagementFilter
    管理用户会话。

  30. ExceptionTranslationFilter
    处理安全异常并转换为 HTTP 响应。

  31. FilterSecurityInterceptor
    执行最终的安全授权检查。

  32. SwitchUserFilter
    处理用户切换功能。


2. 过滤器顺序的重要性
  • 执行顺序
    过滤器的顺序决定了它们对请求的处理顺序,顺序错误可能导致安全漏洞或功能失效。
  • 默认顺序
    通常不需要手动调整过滤器的顺序,Spring Security 已经提供了合理的默认顺序。
  • 自定义顺序
    在特殊情况下,可以通过 SecurityFilterChain API 自定义过滤器的顺序。

3、总结

Spring Security Filters 是处理安全逻辑的核心组件,通过 SecurityFilterChain API 插入到 FilterChainProxy 中。以下是关键点:

要点说明
过滤器列表包含 32 个过滤器,按顺序处理认证、授权、防护等逻辑。
顺序重要性过滤器的顺序非常重要,决定了处理逻辑的正确性。
自定义顺序可以通过 SecurityFilterChain API 自定义顺序。

通过理解 Spring Security Filters 的作用与顺序,开发者可以更好地配置和管理安全逻辑。

ExceptionTranslationFilter 的作用与机制

ExceptionTranslationFilter 是 Spring Security 的核心过滤器之一,用于将 AccessDeniedException 和 AuthenticationException 转换为 HTTP 响应。以下是其核心功能与工作机制:


1. 功能概述
  • 异常处理
    ExceptionTranslationFilter 负责捕获并处理 AccessDeniedException 和 AuthenticationException
  • HTTP 响应
    将异常转换为适当的 HTTP 响应,如重定向到登录页面或返回 403 状态码。

2. 工作机制
  1. 调用后续过滤器
    • ExceptionTranslationFilter 首先调用 FilterChain.doFilter(request, response),执行后续的过滤器和应用程序逻辑。
  2. 处理异常
    • 如果抛出 AuthenticationException 或用户未认证,则启动认证流程:
      • 清除 SecurityContextHolder
      • 将请求保存到 RequestCache,以便认证成功后重放原始请求。
      • 使用 AuthenticationEntryPoint 向客户端请求凭证(如重定向到登录页面或发送 WWW-Authenticate 头)。
    • 如果抛出 AccessDeniedException,则调用 AccessDeniedHandler 处理访问拒绝。
  3. 无异常情况
    • 如果没有抛出异常,ExceptionTranslationFilter 不执行任何操作。

3. 伪代码示例

以下是 ExceptionTranslationFilter 的伪代码:

try { 
    filterChain.doFilter(request, response); // 调用后续过滤器和应用程序 
} catch (AccessDeniedException | AuthenticationException ex) { 
    if (!authenticated || ex instanceof AuthenticationException) { 
        startAuthentication(); // 启动认证流程 
    } else { 
        accessDenied(); // 处理访问拒绝 
    } 
}

4、总结

ExceptionTranslationFilter 是 Spring Security 中用于处理安全异常的核心过滤器,其核心功能与工作机制如下:

功能说明
异常处理捕获并处理 AccessDeniedException 和 AuthenticationException
HTTP 响应将异常转换为适当的 HTTP 响应。
认证流程启动认证流程,保存请求并请求凭证。
访问拒绝处理访问拒绝,调用 AccessDeniedHandler

通过 ExceptionTranslationFilter,Spring Security 实现了灵活且强大的异常处理机制,确保应用程序的安全性。

Spring Security 认证机制概述

Spring Security 提供了全面的认证支持,涵盖了多种认证机制。以下是其核心架构与具体认证方式的总结:


1. 认证架构
  • 抽象架构
    Spring Security 的认证架构是抽象的,适用于多种具体实现。它定义了认证的核心流程,包括认证请求、认证处理、认证结果等。
  • 模块化设计
    通过模块化设计,开发者可以根据需求选择合适的认证机制,并灵活集成到应用中。

2. 具体认证机制

以下是 Spring Security 支持的常见认证机制:

  1. 用户名和密码认证
    最常用的认证方式,用户通过用户名和密码进行认证。

  2. OAuth 2.0 登录
    支持 OpenID Connect 和非标准的 OAuth 2.0 登录(如 GitHub)。

  3. SAML 2.0 登录
    支持基于 SAML 2.0 的单点登录(SSO)。

  4. 中央认证服务器 (CAS)
    集成 CAS 进行认证。

  5. 记住我功能
    在会话过期后仍能记住用户身份。

  6. JAAS 认证
    使用 Java 认证和授权服务(JAAS)进行认证。

  7. OpenID 认证
    支持 OpenID 认证(注意与 OpenID Connect 的区别)。

  8. 预认证场景
    使用外部机制(如 SiteMinder 或 Java EE 安全)进行认证,但仍依赖 Spring Security 进行授权和防护。

  9. X509 认证
    基于 X.509 证书的认证。


3、总结

Spring Security 提供了灵活且全面的认证支持,涵盖了从用户名密码到 OAuth 2.0、SAML 2.0 等多种认证机制。以下是关键点:

要点说明
认证架构抽象的、模块化的设计,适用于多种实现。
认证机制支持用户名密码、OAuth 2.0、SAML 2.0 等多种方式。
灵活性开发者可根据需求选择并集成认证机制。

通过 Spring Security,开发者可以轻松实现安全、灵活的认证功能,满足不同应用场景的需求。

Spring Security Servlet 认证架构

Spring Security 的 Servlet 认证架构是其核心部分,定义了认证的主要组件及其协作方式。以下是其关键组件与工作机制的总结:


1. 核心组件
  1. SecurityContextHolder
    • 存储当前认证用户的详细信息(SecurityContext)。
    • 通过 ThreadLocal 默认实现,确保同一线程内可访问 SecurityContext
  2. SecurityContext
    • 从 SecurityContextHolder 获取,包含当前认证用户的 Authentication 对象。
  3. Authentication
    • 表示用户认证信息,可以是用户提供的凭证或当前认证用户的信息。
  4. GrantedAuthority
    • 授予认证用户的权限(如角色、范围等)。
  5. AuthenticationManager
    • 定义 Spring Security 过滤器如何执行认证的 API。
  6. ProviderManager
    • AuthenticationManager 的最常见实现,委托给多个 AuthenticationProvider 执行认证。
  7. AuthenticationProvider
    • 执行特定类型的认证逻辑。
  8. AuthenticationEntryPoint
    • 用于向客户端请求凭证(如重定向到登录页面或发送 WWW-Authenticate 头)。
  9. AbstractAuthenticationProcessingFilter
    • 用于认证的基础过滤器,展示了认证的高层流程。

2. SecurityContextHolder 的作用与使用

SecurityContextHolder 是 Spring Security 认证模型的核心组件,用于存储当前认证用户的详细信息。以下是其关键点:


1. 作用
  • 存储认证信息
    SecurityContextHolder 包含 SecurityContext,后者存储了当前认证用户的 Authentication 对象。
  • 灵活性
    Spring Security 不关心 SecurityContextHolder 是如何填充的,只要其中包含值,就会被视为当前认证用户。

2. 使用方式
  • 直接设置
    最简单的认证方式是通过代码直接设置 SecurityContextHolder,例如:
    • 步骤
      1. 创建空的 SecurityContext
      2. 创建 Authentication 对象(如 TestingAuthenticationToken)。
      3. 将 Authentication 设置到 SecurityContext 中。
      4. 将 SecurityContext 设置到 SecurityContextHolder

  1. 设置 SecurityContextHolder
    • 创建空的 SecurityContext 并设置 Authentication 对象,例如:
      SecurityContext context = SecurityContextHolder.createEmptyContext(); 
      Authentication authentication = new TestingAuthenticationToken("username", "password", "ROLE_USER"); 
      context.setAuthentication(authentication); 
      SecurityContextHolder.setContext(context);
  2. 获取当前认证用户
    • 从 SecurityContextHolder 获取 SecurityContext 和 Authentication 对象,例如:
      SecurityContext context = SecurityContextHolder.getContext(); 
      Authentication authentication = context.getAuthentication(); 
      String username = authentication.getName(); 
      Object principal = authentication.getPrincipal(); 
      Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities(); 
  3. 线程安全与存储策略
    • 默认使用 ThreadLocal 存储 SecurityContext,确保同一线程内可访问。
    • 支持多种存储策略,如 MODE_GLOBAL(全局共享)和 MODE_INHERITABLETHREADLOCAL(子线程继承)。


3、总结

Spring Security 的 Servlet 认证架构通过一系列核心组件(如 SecurityContextHolderAuthenticationManager 等)实现了灵活且强大的认证功能。以下是关键点:

要点说明
核心组件包括 SecurityContextHolderAuthenticationManager 等。
工作机制通过 SecurityContextHolder 存储和访问认证信息。
线程安全默认使用 ThreadLocal,支持多种存储策略。

通过理解 Spring Security 的 Servlet 认证架构,开发者可以更好地实现和管理认证逻辑,确保应用的安全性。

SecurityContext 和 Authentication 的作用与结构

在 Spring Security 中,SecurityContext 和 Authentication 是核心组件,用于存储和管理用户认证信息。以下是它们的详细说明:


1. SecurityContext
  • 作用
    SecurityContext 是从 SecurityContextHolder 中获取的,用于存储当前认证用户的详细信息。
  • 内容
    包含一个 Authentication 对象,表示当前认证用户的信息。

2. Authentication
  • 作用
    Authentication 在 Spring Security 中主要有两个用途:
    1. 认证输入
      作为 AuthenticationManager 的输入,提供用户凭证(如用户名和密码)。此时,isAuthenticated() 返回 false
    2. 当前认证用户
      表示当前已认证的用户,可以从 SecurityContext 中获取。
  • 内容
    Authentication 包含以下关键信息:
    • principal
      标识用户。在用户名/密码认证中,通常是 UserDetails 的实例。
    • credentials
      用户凭证,通常是密码。认证成功后,凭证通常会被清除以防止泄露。
    • authorities
      用户被授予的高级权限(GrantedAuthority),如角色或范围。

总结

SecurityContext 和 Authentication 是 Spring Security 中用于管理用户认证信息的关键组件。以下是关键点:

组件说明
SecurityContext存储当前认证用户的 Authentication 对象。
Authentication表示用户凭证或当前认证用户,包含 principalcredentials 和 authorities

通过理解 SecurityContext 和 Authentication 的作用与结构,开发者可以更好地实现和管理 Spring Security 的认证逻辑。

GrantedAuthority 的作用与使用

GrantedAuthority 是 Spring Security 中用于表示用户被授予的高级权限的核心组件。以下是其关键点:


1. 作用
  • 表示权限
    GrantedAuthority 表示用户被授予的权限,通常是角色(如 ROLE_ADMINISTRATOR)或范围(如 SCOPE_READ)。
  • 应用范围
    这些权限通常是应用范围内的,不针对特定领域对象(如员工编号 54)。

2. 获取方式
  • 从 Authentication 获取
    通过 Authentication.getAuthorities() 方法获取一个 GrantedAuthority 对象的集合。
  • 加载方式
    在使用用户名/密码认证时,GrantedAuthority 通常由 UserDetailsService 加载。

3. 使用场景
  • 授权配置
    GrantedAuthority 用于配置 Web 授权、方法授权和领域对象授权。
  • 权限设计
    由于 GrantedAuthority 是应用范围的权限,不应用于表示特定领域对象的权限(如员工编号 54)。对于这种需求,应使用 Spring Security 的领域对象安全功能。

4、总结

GrantedAuthority 是 Spring Security 中用于管理用户权限的关键组件。以下是关键点:

要点说明
作用表示用户被授予的高级权限(如角色或范围)。
获取方式通过 Authentication.getAuthorities() 获取。
使用场景用于授权配置,不适用于特定领域对象的权限。

通过理解 GrantedAuthority 的作用与使用,开发者可以更好地实现和管理 Spring Security 的权限逻辑。

AuthenticationManager 的作用与实现

AuthenticationManager 是 Spring Security 中定义认证逻辑的核心 API。以下是其关键点:


1. 作用
  • 定义认证逻辑
    AuthenticationManager 定义了 Spring Security 过滤器如何执行认证。
  • 设置认证结果
    认证成功后,返回的 Authentication 对象会被设置到 SecurityContextHolder 中。

2. 使用场景
  • 集成过滤器
    如果与 Spring Security 的过滤器集成,认证逻辑由 AuthenticationManager 处理。
  • 直接设置
    如果未使用 Spring Security 的过滤器,可以直接设置 SecurityContextHolder,而不需要使用 AuthenticationManager

3. 实现
  • 常见实现
    ProviderManager 是 AuthenticationManager 的最常见实现。
  • 灵活性
    AuthenticationManager 的实现可以是任何形式,但通常使用 ProviderManager

4、总结

AuthenticationManager 是 Spring Security 中用于管理认证逻辑的关键组件。以下是关键点:

要点说明
核心作用定义认证逻辑并设置认证结果。
使用场景集成过滤器或直接设置 SecurityContextHolder
常见实现ProviderManager 是最常见的实现。

通过理解 AuthenticationManager 的作用与实现,开发者可以更好地实现和管理 Spring Security 的认证逻辑。

ProviderManager 的作用与特性

ProviderManager 是 Spring Security 中最常用的 AuthenticationManager 实现,负责管理认证流程并支持多种认证机制。以下是其关键特性:

1、ProviderManager 是 AuthenticationManager 最常用的实现。它将认证任务委托给一组 AuthenticationProvider。每个 AuthenticationProvider 都有机会决定认证是否成功、失败,或者表示无法做出决定并交由下游 AuthenticationProvider 处理。如果所有配置的 AuthenticationProvider 都无法完成认证,则认证会失败,并抛出 ProviderNotFoundException,这是一种特殊的 AuthenticationException,表明 ProviderManager 未配置为支持传入的 Authentication 类型。

2、在实践中,每个AuthenticationProvider都知道如何执行特定类型的身份验证。例如,一个AuthenticationProvider可能能够验证用户名/密码,而另一个可能能够验证SAML断言。这允许每个AuthenticationProvider执行一种非常特定的身份验证类型,同时支持多种类型的身份验证,并且只公开一个AuthenticationManager bean。
ProviderManager还允许配置可选的父AuthenticationManager,当没有AuthenticationProvider可以执行身份验证时,会参考该AuthenticationManager。父级可以是任何类型的AuthenticationManager,但它通常是ProviderManager的实例。

事实上,多个 ProviderManager 实例可能共享同一个父级 AuthenticationManager。这种情况在以下场景中较为常见:存在多个 SecurityFilterChain 实例,它们具有一些共同的认证机制(共享的父级 AuthenticationManager),但也使用不同的认证机制(不同的 ProviderManager 实例)。

默认情况下,ProviderManager 会尝试清除成功认证请求返回的 Authentication 对象中的敏感凭证信息。这样可以防止密码等敏感信息在 HttpSession 中保留过久。


1. 核心功能
  • 委托认证
    ProviderManager 委托给一组 AuthenticationProvider 执行认证,每个 AuthenticationProvider 负责特定类型的认证(如用户名/密码或 SAML 断言)。
  • 认证流程
    每个 AuthenticationProvider 可以决定认证成功、失败或无法处理并交给下游 AuthenticationProvider。如果所有 AuthenticationProvider 都无法认证,则抛出 ProviderNotFoundException

2. 父级认证机制
  • 可选父级
    ProviderManager 可以配置一个可选的父级 AuthenticationManager,当所有 AuthenticationProvider 都无法认证时,会咨询父级。
  • 共享父级
    多个 ProviderManager 实例可以共享同一个父级 AuthenticationManager,适用于多个 SecurityFilterChain 实例有共同认证机制但使用不同认证方式的场景。

3. 敏感信息清除
  • 默认行为
    ProviderManager 默认会清除成功认证请求返回的 Authentication 对象中的敏感信息(如密码),以防止这些信息在 HttpSession 中保留过久。
  • 缓存问题
    如果 Authentication 对象包含缓存中的用户对象(如 UserDetails 实例),清除敏感信息后可能导致无法使用缓存值进行认证。解决方法包括:
    1. 在缓存实现或 AuthenticationProvider 中创建对象的副本。
    2. 禁用 ProviderManager 的 eraseCredentialsAfterAuthentication 属性。

4、总结

ProviderManager 是 Spring Security 中用于管理认证逻辑的核心组件,支持多种认证机制和父级认证。以下是关键点:

要点说明
认证委托委托给一组 AuthenticationProvider 执行认证。
父级认证支持配置可选的父级 AuthenticationManager
敏感信息清除默认清除认证成功后的敏感信息,需注意缓存问题。

通过理解 ProviderManager 的作用与特性,开发者可以更好地实现和管理 Spring Security 的认证逻辑。

AuthenticationProvider 的作用与类型

AuthenticationProvider 是 Spring Security 中用于执行特定类型认证的核心组件。以下是其关键点:


1. 作用
  • 执行认证
    每个 AuthenticationProvider 负责特定类型的认证,例如用户名/密码认证或 JWT 认证。
  • 多类型支持
    多个 AuthenticationProvider 可以注入到 ProviderManager 中,以支持多种认证机制。

2. 常见类型
  • DaoAuthenticationProvider
    支持基于用户名/密码的认证,通常与 UserDetailsService 结合使用。
  • JwtAuthenticationProvider
    支持基于 JWT 令牌的认证,通常用于无状态应用。

3、总结

AuthenticationProvider 是 Spring Security 中用于管理特定类型认证的核心组件。以下是关键点:

要点说明
核心作用执行特定类型的认证。
常见类型DaoAuthenticationProvider 和 JwtAuthenticationProvider

通过理解 AuthenticationProvider 的作用与类型,开发者可以更好地实现和管理 Spring Security 的认证逻辑。

AuthenticationEntryPoint 的作用与使用场景

AuthenticationEntryPoint 是 Spring Security 中用于处理未认证请求的核心组件,其主要作用是向客户端发送 HTTP 响应以请求凭证。以下是其关键点:


1. 作用
  • 请求凭证
    当客户端未提供凭证或凭证无效时,AuthenticationEntryPoint 会发送 HTTP 响应,要求客户端提供凭证(如重定向到登录页面或返回 WWW-Authenticate 头)。
  • 处理未认证请求
    用于处理客户端对未授权资源的未认证请求。

2. 使用场景
  • 客户端未提供凭证
    当客户端未主动包含凭证(如用户名/密码)时,AuthenticationEntryPoint 会被触发。
  • 客户端凭证无效
    当客户端提供的凭证无效或认证失败时,AuthenticationEntryPoint 会要求重新提供凭证。

3. 常见实现
  • 重定向到登录页面
    通过重定向到登录页面,提示用户输入凭证。
  • 返回 WWW-Authenticate 头
    返回 WWW-Authenticate 头,要求客户端提供认证信息(如 Basic 或 Bearer 认证)。

4、总结

AuthenticationEntryPoint 是 Spring Security 中用于处理未认证请求的关键组件。以下是关键点:

要点说明
核心作用向客户端发送 HTTP 响应以请求凭证。
使用场景客户端未提供凭证或凭证无效时触发。
常见实现重定向到登录页面或返回 WWW-Authenticate 头。

通过理解 AuthenticationEntryPoint 的作用与使用场景,开发者可以更好地实现和管理 Spring Security 的认证逻辑。

AbstractAuthenticationProcessingFilter 的作用与流程

AbstractAuthenticationProcessingFilter 是 Spring Security 中用于处理用户认证请求的基类过滤器。它负责从请求中提取凭证并执行认证。以下是其核心流程与功能:


1. 创建 Authentication 对象
  • 提取凭证
    当用户提交凭证时,AbstractAuthenticationProcessingFilter 从 HttpServletRequest 中提取凭证并创建 Authentication 对象。
  • 子类实现
    具体的 Authentication 类型取决于 AbstractAuthenticationProcessingFilter 的子类。例如,UsernamePasswordAuthenticationFilter 会创建 UsernamePasswordAuthenticationToken

2. 执行认证
  • 调用 AuthenticationManager
    创建的 Authentication 对象会被传递给 AuthenticationManager 进行认证。

3. 认证失败处理
  • 清理 SecurityContextHolder
    认证失败时,SecurityContextHolder 会被清除。
  • 记住我服务
    调用 RememberMeServices.loginFail ,如果未配置记住我功能,则无操作。
  • 失败处理器
    调用 AuthenticationFailureHandler 处理认证失败。

4. 认证成功处理
  • 会话策略通知
    通知 SessionAuthenticationStrategy 新的登录事件。
  • 设置 SecurityContextHolder
    将认证成功的 Authentication 对象设置到 SecurityContextHolder 中,稍后由 SecurityContextPersistenceFilter 保存到 HttpSession
  • 记住我服务
    调用 RememberMeServices.loginSuccess ,如果未配置记住我功能,则无操作。
  • 发布事件
    ApplicationEventPublisher 发布 InteractiveAuthenticationSuccessEvent
  • 成功处理器
    调用 AuthenticationSuccessHandler 处理认证成功。

5、总结

AbstractAuthenticationProcessingFilter 是 Spring Security 中用于处理用户认证请求的核心组件。以下是关键点:

流程说明
创建 Authentication从请求中提取凭证并创建 Authentication 对象。
执行认证调用 AuthenticationManager 进行认证。
认证失败处理清理 SecurityContextHolder 并调用失败处理器。
认证成功处理设置 SecurityContextHolder 并调用成功处理器。

通过理解 AbstractAuthenticationProcessingFilter 的作用与流程,开发者可以更好地实现和管理 Spring Security 的认证逻辑。

用户名/密码认证

验证用户名和密码是用户认证的最常见方式之一。因此,Spring Security 提供了全面的支持来实现用户名和密码认证。

1、读取用户名和密码

Spring Security 提供了以下内置机制,用于从 HttpServletRequest 中读取用户名和密码:

认证方式

  1. 表单认证
    通过 HTML 表单提交用户名和密码。最常见的认证方式,适用于 Web 应用。
  2. 基本认证
    通过 HTTP 基本认证头(Authorization: Basic)提交用户名和密码。简单但安全性较低,适用于 API 或内部系统。
  3. 摘要认证
    通过 HTTP 摘要认证头(Authorization: Digest)提交用户名和密码。比基本认证更安全,但实现复杂,适用于高安全需求的场景。
1.表单登录(Form Login

Spring Security 提供了通过 HTML 表单提交用户名和密码的支持。本节详细介绍了在 Spring Security 中基于表单的身份验证是如何工作的。

让我们来看看在 Spring Security 中基于表单的登录是如何进行的。首先,我们会看到用户是如何被重定向到登录表单的。

该图基于我们的 SecurityFilterChain 图进行构建。

  1. 第一步:用户向未授权的资源(例如 /private)发出未经认证的请求。
  2. 第二步:Spring Security 的 FilterSecurityInterceptor 通过抛出 AccessDeniedException 表示该未经认证的请求被拒绝。
  3. 第三步:由于用户未认证,ExceptionTranslationFilter 启动身份验证流程,并使用配置的 AuthenticationEntryPoint 将用户重定向到登录页面。在大多数情况下,AuthenticationEntryPoint 是 LoginUrlAuthenticationEntryPoint 的实例。
  4. 第四步:浏览器随后请求被重定向到的登录页面。
  5. 第五步:应用程序中的某些部分必须渲染登录页面。

当用户提交用户名和密码时,UsernamePasswordAuthenticationFilter 会对用户名和密码进行验证。由于 UsernamePasswordAuthenticationFilter 继承自 AbstractAuthenticationProcessingFilter,因此该图看起来应该非常相似。

该图基于我们的 SecurityFilterChain 图进行构建。

  1. 第一步:当用户提交用户名和密码时,UsernamePasswordAuthenticationFilter 会从 HttpServletRequest 中提取用户名和密码,并创建一个 UsernamePasswordAuthenticationToken,这是一种 Authentication 类型。
  2. 第二步:接下来,UsernamePasswordAuthenticationToken 会被传递到 AuthenticationManager 进行认证。AuthenticationManager 的具体行为取决于用户信息的存储方式。
  3. 第三步:如果认证失败,则执行以下操作:
    • 清除 SecurityContextHolder
    • 调用 RememberMeServices.loginFail 。如果未配置记住我功能,则此操作无效。
    • 调用 AuthenticationFailureHandler
  4. 第四步:如果认证成功,则执行以下操作:
    • 通知 SessionAuthenticationStrategy 有新登录。
    • 将 Authentication 设置到 SecurityContextHolder 中。
    • 调用 RememberMeServices.loginSuccess 。如果未配置记住我功能,则此操作无效。
    • ApplicationEventPublisher 发布一个 InteractiveAuthenticationSuccessEvent 事件。
    • 调用 AuthenticationSuccessHandler。通常这是一个 SimpleUrlAuthenticationSuccessHandler,它会重定向到由 ExceptionTranslationFilter 在重定向到登录页面时保存的请求。

Spring Security 的表单登录功能默认是启用的。然而,一旦提供了任何基于 Servlet 的配置,就必须显式地配置基于表单的登录。以下是一个最小的显式 Java 配置示例:

表单登录配置

protected void configure(HttpSecurity http) {
    http 
        // ...
        .formLogin(withDefaults());
}

在此配置中,Spring Security 会渲染一个默认的登录页面。大多数生产环境中的应用程序都需要自定义登录表单。

以下配置演示了如何提供自定义登录表单:

自定义登录表单配置

protected void configure(HttpSecurity http) throws Exception {
    http 
        // ... 
        .formLogin(form -> form 
            .loginPage("/login")
            .permitAll()
        );
}

当在 Spring Security 配置中指定了登录页面时,您需要负责渲染该页面。以下是一个 Thymeleaf 模板示例,它生成一个符合 /login 页面的 HTML 登录表单。

登录表单 - src/main/resources/templates/login.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"  xmlns:th="https://www.thymeleaf.org"> 
	<head>
		<title>请登录</title>
	</head>
	<body>
		<h1>请登录</h1>
		<div th:if="${param.error}"> 
			用户名或密码无效。</div>
		<div th:if="${param.logout}"> 
			您已成功登出。</div>
		<form th:action="@{/login}" method="post">
			<div>
			<input type="text" name="username" placeholder="用户名"/>
			</div>
			<div>
			<input type="password" name="password" placeholder="密码"/>
			</div>
			<input type="submit" value="登录" />
		</form>
	</body>
</html>

默认 HTML 表单的关键点:

  1. 表单应通过 POST 方法提交到 /login
  2. 表单需要包含 CSRF 令牌,Thymeleaf 会自动处理这一点。
  3. 表单应使用名为 username 的参数传递用户名。
  4. 表单应使用名为 password 的参数传递密码。
  5. 如果检测到 HTTP 参数 error,表示用户提供的用户名或密码无效。
  6. 如果检测到 HTTP 参数 logout,表示用户已成功登出。

大多数用户只需自定义登录页面即可。但如果需要,上述所有内容都可以通过额外配置进行自定义。

如果您使用 Spring MVC,则需要一个控制器来映射到我们创建的登录模板。以下是一个最小化示例:

LoginController

@Controller 
class LoginController {
	@GetMapping("/login")
	String login() {
		return "login";
	}
}

说明:

  • CSRF 令牌:用于防止跨站请求伪造攻击,Spring Security 默认启用此功能。
  • Thymeleaf:一种与 Spring 集成的模板引擎,适合生成动态 HTML 页面。
  • 控制器:在 Spring MVC 中,控制器负责处理请求并返回视图(如登录页面)。

2. 基本认证(Basic Authentication

本节详细介绍了 Spring Security 如何为基于 Servlet 的应用程序提供 HTTP 基本认证支持。让我们来看看 HTTP 基本认证在 Spring Security 中的工作原理。首先,我们会看到 WWW-Authenticate 标头被发送回未认证的客户端。


该图基于我们的 SecurityFilterChain 图进行构建。

  1. 第一步:用户向未授权的资源 /private 发出未经认证的请求。
  2. 第二步:Spring Security 的 FilterSecurityInterceptor 通过抛出 AccessDeniedException 表示该未经认证的请求被拒绝。
  3. 第三步:由于用户未认证,ExceptionTranslationFilter 启动身份验证流程。配置的 AuthenticationEntryPoint 是 BasicAuthenticationEntryPoint 的实例,它会发送 WWW-Authenticate 标头。RequestCache 通常是 NullRequestCache,它不会保存请求,因为客户端能够重放其最初发出的请求。

当客户端收到 WWW-Authenticate 标头时,它知道应该使用用户名和密码重试请求。以下是用户名和密码处理的流程。

该图基于我们的 SecurityFilterChain 图进行构建。

  1. 第一步:当用户提交用户名和密码时,BasicAuthenticationFilter 会从 HttpServletRequest 中提取用户名和密码,并创建一个 UsernamePasswordAuthenticationToken,这是一种 Authentication 类型。
  2. 第二步:接下来,UsernamePasswordAuthenticationToken 会被传递到 AuthenticationManager 进行认证。AuthenticationManager 的具体行为取决于用户信息的存储方式。
  3. 第三步:如果认证失败,则执行以下操作:
    • 清除 SecurityContextHolder
    • 调用 RememberMeServices.loginFail 。如果未配置记住我功能,则此操作无效。
    • 调用 AuthenticationEntryPoint 以再次发送 WWW-Authenticate 标头。
  4. 第四步:如果认证成功,则执行以下操作:
    • 将 Authentication 设置到 SecurityContextHolder 中。
    • 调用 RememberMeServices.loginSuccess 。如果未配置记住我功能,则此操作无效。
    • BasicAuthenticationFilter 调用 FilterChain.doFilter(request, response) 以继续执行应用程序的其余逻辑。

Spring Security 的 HTTP 基本认证支持默认是启用的。然而,一旦提供了任何基于 Servlet 的配置,就必须显式地配置 HTTP 基本认证。

以下是一个最小的显式配置示例:

显式 HTTP 基本认证配置

protected void configure(HttpSecurity http) {
    http 
        // ...
        .httpBasic(withDefaults());
}

补充说明:

  • HTTP 基本认证:一种简单的认证机制,客户端通过 Authorization 标头发送 Base64 编码的用户名和密码。
  • AuthenticationManager:负责验证用户凭据的核心组件。
  • RememberMeServices:用于处理“记住我”功能,如果未配置,则相关操作无效。
  • SecurityContextHolder:用于存储当前的安全上下文信息,包括认证信息。
3. 摘要认证(Digest Authentication

本节详细介绍了 Spring Security 如何通过 DigestAuthenticationFilter 提供摘要认证支持。

在现代应用程序中,您不应使用摘要认证,因为它被认为是不安全的。最明显的问题是,您必须以明文、加密或 MD5 格式存储密码。所有这些存储格式都被认为是不安全的。相反,您应使用单向自适应密码哈希(如 bCrypt、PBKDF2、SCrypt 等)存储凭据,而摘要认证不支持这些哈希方式。

摘要认证试图解决基本认证的许多弱点,特别是通过确保凭据不会以明文形式通过网络发送。许多浏览器支持摘要认证。

HTTP 摘要认证的标准由 RFC 2617 定义,该标准更新了 RFC 2069 规定的早期摘要认证标准。大多数用户代理实现 RFC 2617。Spring Security 的摘要认证支持与 RFC 2617 规定的“auth”保护质量(qop)兼容,同时也向后兼容 RFC 2069。如果您需要使用未加密的 HTTP(即没有 TLS/HTTPS)并希望最大限度地提高认证过程的安全性,摘要认证曾被视为更具吸引力的选择。然而,每个人都应使用 HTTPS。

摘要认证的核心是“nonce”。这是服务器生成的值。Spring Security 的 nonce 采用以下格式:

摘要语法

base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key))

  • expirationTime:nonce 过期的日期和时间,以毫秒表示。
  • key:用于防止 nonce 令牌被修改的私钥。

您需要确保使用 NoOpPasswordEncoder 配置不安全的明文密码存储。以下是一个使用 Java 配置摘要认证的示例:

摘要认证配置

@Autowired 
UserDetailsService userDetailsService;
 
DigestAuthenticationEntryPoint entryPoint() {
    DigestAuthenticationEntryPoint result = new DigestAuthenticationEntryPoint();
    result.setRealmName("My  App Realm");
    result.setKey("3028472b-da34-4501-bfd8-a355c42bdf92"); 
}
 
DigestAuthenticationFilter digestAuthenticationFilter() {
    DigestAuthenticationFilter result = new DigestAuthenticationFilter();
    result.setUserDetailsService(userDetailsService); 
    result.setAuthenticationEntryPoint(entryPoint()); 
}
 
protected void configure(HttpSecurity http) throws Exception {
    http 
        // ...
        .exceptionHandling(e -> e.authenticationEntryPoint(authenticationEntryPoint())) 
        .addFilterBefore(digestFilter());
}

补充说明:

  • 摘要认证:一种比基本认证更安全的认证机制,但因其密码存储方式的局限性,已不再推荐使用。
  • nonce:用于防止重放攻击的一次性值。
  • NoOpPasswordEncoder:明文密码编码器,仅用于测试或演示,不应用于生产环境。
  • HTTPS:推荐在所有生产环境中使用 HTTPS 来确保数据的安全传输。

密码存储(Password Storage)

存储机制

每种支持的读取用户名和密码的机制都可以利用以下任何一种支持的存储机制:

  • 简单存储:内存认证
  • 关系型数据库:JDBC 认证
  • 自定义数据存储:UserDetailsService
  • LDAP 存储:LDAP 认证

章节总结

  • 内存认证(In Memory)
  • JDBC 认证(JDBC)
  • 用户详情(UserDetails)
  • 用户详情服务(UserDetailsService)
  • 密码编码器(PasswordEncoder)
  • DAO 认证提供者(DaoAuthenticationProvider)
  • LDAP 认证(LDAP)

内存认证


Spring Security 的 InMemoryUserDetailsManager 实现了 UserDetailsService 接口,为基于用户名/密码的认证提供支持,并将这些信息存储在内存中。InMemoryUserDetailsManager 通过实现 UserDetailsManager 接口来管理 UserDetails。当 Spring Security 配置为接受用户名/密码进行认证时,会使用基于 UserDetails 的认证。

在这个示例中,我们使用 Spring Boot CLI 对密码 password 进行编码,得到编码后的密码:{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW 。

InMemoryUserDetailsManager Java 配置

@Bean 
public UserDetailsService users() {
    UserDetails user = User.builder() 
        .username("user")
        .password("{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW") 
        .roles("USER")
        .build();
    UserDetails admin = User.builder() 
        .username("admin")
        .password("{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW") 
        .roles("USER", "ADMIN")
        .build();
    return new InMemoryUserDetailsManager(user, admin);
}

上述示例以安全格式存储密码,但在入门体验方面仍有许多不足。

在以下示例中,我们使用 User.withDefaultPasswordEncoder 来确保存储在内存中的密码受到保护。然而,它并不能防止通过反编译源代码获取密码。因此,User.withDefaultPasswordEncoder 仅适用于“入门”,不应用于生产环境。

使用 User.withDefaultPasswordEncoder 的 InMemoryUserDetailsManager

@Bean 
public UserDetailsService users() {
    // 构建器将确保密码在存储到内存之前被编码 
    UserBuilder users = User.withDefaultPasswordEncoder(); 
    UserDetails user = users 
        .username("user")
        .password("password")
        .roles("USER")
        .build();
    UserDetails admin = users 
        .username("admin")
        .password("password")
        .roles("USER", "ADMIN")
        .build();
    return new InMemoryUserDetailsManager(user, admin);
}

在基于 XML 的配置中,没有简单的方法使用 User.withDefaultPasswordEncoder 。对于演示或入门,您可以选择在密码前添加 {noop} 前缀,表示不使用编码。

<user-service> {noop} XML 配置

<user-service>
    <user name="user"
        password="{noop}password"
        authorities="ROLE_USER" />
    <user name="admin"
        password="{noop}password"
        authorities="ROLE_USER,ROLE_ADMIN" />
</user-service>

补充说明:

  • 内存认证:适用于小型或测试环境,用户信息直接存储在内存中。
  • 密码编码:推荐使用 bcrypt 等安全编码方式存储密码。
  • {noop} 前缀:表示密码未编码,仅适用于演示或入门场景。
  • 生产环境:在生产环境中,应避免使用明文或默认密码编码器,推荐使用安全的密码哈希算法。

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

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

相关文章

数据结构与算法效率分析:时间复杂度与空间复杂度详解(C语言)

1. 算法效率 1.1 如何衡量一个算法的好坏&#xff1f; 在计算机程序设计中&#xff0c;衡量算法优劣的核心标准是效率。但效率不仅指运行速度&#xff0c;还需要综合以下因素&#xff1a; 时间因素&#xff1a;算法执行所需时间 空间因素&#xff1a;算法运行占用的内存空间…

数据类设计_图片类设计之4_规则类图形混合算法(前端架构)

前言 学的东西多了,要想办法用出来.C和C是偏向底层的语言,直接与数据打交道.尝试做一些和数据方面相关的内容 引入 接续上一篇,讨论图片类型设计出来后在场景中如何表达,以及图片的混合算法.前面的内容属于铺垫和基础,这篇内容和实际联系起来了. 背景图和前景图 这里笔者想先…

从零使用docker并安装部署mysql8.3.0容器

在开始使用docker到完成mysql的安装部署&#xff0c;中间有很多的坑等着 安装docker并配置 sudo yum install docker-ce 启动docker并设置开机启动项 sudo systemctl start docker sudo systemctl enable docker查看docker是否启动 sudo systemctl status docker 或者直接…

cpu 多级缓存L1、L2、L3 与主存关系

现代 CPU 的多级缓存&#xff08;L1、L2、L3&#xff09;和主存&#xff08;DRAM&#xff09;构成了一个层次化的内存系统&#xff0c;旨在通过减少内存访问延迟和提高数据访问速度来优化计算性能。以下是对多级缓存和主存的详细解析&#xff1a; 1. 缓存层次结构 现代 CPU 通…

基于Python+SQLite实现校园信息化统计平台

一、项目基本情况 概述 本项目以清华大学为预期用户&#xff0c;作为校内信息化统计平台进行服务&#xff0c;建立网页端和移动端校内信息化统计平台&#xff0c;基于Project_1的需求实现。 本项目能够满足校内学生团体的几类统计需求&#xff0c;如活动报名、实验室招募、多…

[多线程]基于阻塞队列(Blocking Queue)的生产消费者模型的实现

标题&#xff1a;[多线程]基于阻塞队列(Blocking Queue)的生产消费者模型的实现 水墨不写bug 文章目录 一、生产者消费者模型特点&#xff1a;二、实现2.1详细解释1. 成员变量2. 构造函数3. Isfull 和 Isempty4. Push 函数5. Pop 函数6. 析构函数7. GetSize 函数 三、总结与多线…

vue组件库el-menu导航菜单设置index,地址不会变更的问题

请先确认 1.路由已配置好 route-index.js如下&#xff0c; 2.view-ProHome.vue中已预留路由展示位 3.导航菜单复制组件库&#xff0c;并做修改 其中index与路由配置的地址一致 运行后发现点击菜单&#xff0c;url地址还是不变&#xff0c;查看组件库 Element - The worlds …

MySQL 优化方案

一、MySQL 查询过程 MySQL 查询过程是指从客户端发送 SQL 语句到 MySQL 服务器&#xff0c;再到服务器返回结果集的整个过程。这个过程涉及多个组件的协作&#xff0c;包括连接管理、查询解析、优化、执行和结果返回等。 1.1 查询过程的关键组件 连接管理器&#xff1a;管理…

智能对话小程序功能优化day1-登录鉴权

目录 1.数据库表构建。 2.完善登录相关的实例对象。 3.登录相关功能实现。 4.小程序效果。 最近尝试下trae加入claude3.7后的读图生成代码功能&#xff0c;可以看到简单的页面一次性生成确实准确率高了不少&#xff0c;想起来之前笔记中开发的智能问答小程序功能还是有些简…

MinIO的预签名直传机制

我们传统使用MinIo做OSS对象存储的应用方式往往都是在后端配置与MinIO的连接和文件上传下载的相关接口&#xff0c;然后我们在前端调用这些接口完成文件的上传下载机制&#xff0c;但是&#xff0c;当并发量过大&#xff0c;频繁访问会对后端的并发往往会对服务器造成极大的压力…

Qt开源控件库(qt-material-widgets)的编译及使用

项目简介 qt-material-widgets是一个基于 Qt 小部件的 Material Design 规范实现。 项目地址 项目地址&#xff1a;qt-material-widgets 本地构建环境 Win11 家庭中文版 VS2019 Qt5.15.2 (MSVC2019) 本地构建流程 克隆后的目录结构如图&#xff1a; 直接使用Qt Crea…

用python批量生成文件夹

问题描述 当批量生成文件夹时&#xff0c;手动右键创建文件夹是一个繁琐的过程&#xff0c;尤其是文件夹的命名过程。假设从3月10日到3月19日&#xff0c;每天要为某个日常工作创建一个名为2025031x的文件夹&#xff0c;手动创建文件夹并命名费时费力。 百度给出了以下四种方法…

【MySQL】基本操作 —— DDL

目录 DDLDDL 常用操作对数据库的常用操作查看所有数据库创建数据库切换、显示当前数据库删除数据库修改数据库编码 对表的常用操作创建表数据类型数值类型日期和时间类型字符串类型 查看当前数据库所有表查看指定表的创建语句查看指定表结构删除表 对表结构的常用操作给表添加字…

游戏引擎学习第152天

仓库:https://gitee.com/mrxiao_com/2d_game_3 回顾昨天的内容 这个节目展示了我们如何从零开始制作一款完整的游戏。我们不使用任何游戏引擎或库&#xff0c;而是从头开始创建一款游戏&#xff0c;整个开发过程都会呈现给大家。你将能够看到每一行代码的编写&#xff0c;了解…

考研数学非数竞赛复习之Stolz定理求解数列极限

在非数类大学生数学竞赛中&#xff0c;Stolz定理作为一种强大的工具&#xff0c;经常被用来解决和式数列极限的问题&#xff0c;也被誉为离散版的’洛必达’方法&#xff0c;它提供了一种简洁而有效的方法&#xff0c;使得原本复杂繁琐的极限计算过程变得直观明了。本文&#x…

故障诊断——neo4j入门

文章目录 neo4jQuickStartDemo neo4j QuickStart 详情可见博客&#xff1a;https://www.cnblogs.com/nhdlb/p/18703804&#xff0c;使用docker拉取最近的一个版本进行创建 docker run -it -d -p 7474:7474 -p 7687:7687 \ -v /disk5/neo4j_docker/data:/data \ -v /disk5/ne…

【JavaWeb】快速入门——HTMLCSS

文章目录 一、 HTML简介1、HTML概念2、HTML文件结构3、可视化网页结构 二、 HTML标签语法1、标题标签2、段落标签3、超链接4、换行5、无序列表6、路径7、图片8、块1 盒子模型2 布局标签 三、 使用HTML表格展示数据1、定义表格2、合并单元格横向合并纵向合并 四、 使用HTML表单收…

若依框架-给sys_user表添加新字段并获取当前登录用户的该字段值

目录 添加字段 修改SysUser类 修改SysUserMapper.xml 修改user.js 前端获取字段值 添加字段 若依框架的sys_user表是没有age字段的&#xff0c;但由于业务需求&#xff0c;我需要新添加一个age字段&#xff1a; 修改SysUser类 添加age字段后&#xff0c;要在SysUser类 …

前端监测窗口尺寸和元素尺寸变化的方法

前端监测窗口尺寸变化和元素尺寸变化的方法 window.resize 简介 window.resize事件是浏览器提供的一种事件&#xff0c;用于监听窗口大小的改变。这意味着当用户调整浏览器窗口大小时&#xff0c;相关的JavaScript代码将被触发执行。这为开发者提供了一种机制&#xff0c;可…

ubuntu 部署deepseek

更新 apt update 升级 apt upgrade 格式化硬盘 mkfs.ext4 /dev/sdb 安装nginx 查看端口 一、安装Ollama Ollama是一个开源的大型语言模型&#xff08;LLM&#xff09;推理服务器&#xff0c;为用户提供了灵活、安全和高性能的语言模型推理解决方案。 ollama/docs/linux.m…