HttpSecurity各项配置

在 Spring Security 中,HttpSecurity 是用于配置 Web 层面安全策略的核心构建器(Builder)。它的核心使命是实现双重安全保障:认证(Authentication,解决“你是谁”的问题)与授权(Authorization,解决“你能做什么”的问题)。

随着 Spring Security 6.x 全面弃用旧版的 WebSecurityConfigurerAdapter,目前官方推荐采用基于 @Bean 的 Lambda 函数式配置方式。以下是 HttpSecurity 中各种常见配置的详细解读及配置示例:

请求授权配置 (authorizeHttpRequests)

这是最核心的配置之一,用于定义 URL 级别的访问控制规则。它遵循“先匹配先生效”的原则,因此宽泛的规则必须放在具体规则之后。

  • requestMatchers():指定需要匹配的 URL 路径(新版推荐使用此方法替代旧的 antMatchers())。
  • permitAll():无条件允许所有用户访问该路径(常用于公开接口、静态资源等)。
  • hasRole("ADMIN"):要求访问者必须具备指定的角色(如 ADMIN)。
  • authenticated():要求访问者必须是已认证的登录用户。
  • anyRequest():匹配所有其他未被前面规则拦截的请求。
.authorizeHttpRequests(auth -> auth
    .requestMatchers("/public/**").permitAll()       // /public 下路径允许所有访问
    .requestMatchers("/admin/**").hasRole("ADMIN")   // /admin 下路径需管理员角色
    .anyRequest().authenticated()                    // 其它所有请求都需要认证
)

表单登录配置 (formLogin)

用于配置基于表单的身份验证行为,支持自定义登录页面及成功/失败后的跳转逻辑。

  • loginPage("/login"):指定自定义的前端登录页面路径。
  • defaultSuccessUrl("/home", true):设置登录成功后的默认跳转页面。
  • failureUrl("/login?error=true"):设置登录失败后的重定向地址。
  • permitAll():必须将登录页及相关处理端点开放给未认证用户,否则会陷入重定向死循环。
.formLogin(form -> form
    .loginPage("/login")              // 自定义登录页面
    .permitAll()                      // 登录页面允许所有访问
    .defaultSuccessUrl("/home", true) // 登录成功后跳转主页
)

前后端分离项目一半不需要。

登出配置 (logout)

用于自定义用户的退出登录行为。

  • logoutUrl("/logout"):触发登出操作的 URL。
  • logoutSuccessUrl("/login?logout"):登出成功后跳转的页面。
  • invalidateHttpSession(true):登出时使当前的 Session 失效。
  • deleteCookies("JSESSIONID"):清除浏览器中的相关 Cookie。
.logout(logout -> logout
    .logoutUrl("/logout")
    .logoutSuccessUrl("/login?logout")
    .invalidateHttpSession(true)
    .deleteCookies("JSESSIONID")
)

CSRF 防护配置 (csrf)

跨站请求伪造(CSRF)防护默认是开启的,它会要求所有状态变更请求(POST, PUT, DELETE)携带 _csrf 令牌。初学者常因前端未传 Token 而遇到 403 错误。如果是纯前后端分离且使用 JWT 的项目,通常会选择关闭它。

.csrf(csrf -> csrf.disable()) // 禁用 CSRF 保护

HTTP Basic 认证 (httpBasic)

通常用于 RESTful API 的简单认证,客户端需要在请求头中提供用户名和密码。

.httpBasic(Customizer.withDefaults()) // 启用默认的 HTTP Basic 认证

会话管理配置 (sessionManagement)

用于控制 Session 的创建策略以及并发登录限制。

  • maximumSessions(1):限制同一用户的最大并发会话数。
  • maxSessionsPreventsLogin(true):当达到最大会话数时,阻止新的登录尝试。
.sessionManagement(session -> session
    .maximumSessions(1)
    .maxSessionsPreventsLogin(true)
)

// 无状态会话  JWT使用
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))

异常处理配置 (exceptionHandling)

用于自定义当用户未认证或无权限时的响应行为。

// 配置自定义认证入口点  
.exceptionHandling(ex -> ex  
        .authenticationEntryPoint(customAuthenticationEntryPoint) // 认证失败处理 
        .accessDeniedHandler(accessDeniedHandler)  // 授权失败处理
) 
@Slf4j  
@Component  
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {  
  
    private final ObjectMapper objectMapper = new ObjectMapper();  
  
    @Override  
    public void commence(HttpServletRequest request, HttpServletResponse response,  
                         AuthenticationException authException) throws IOException {  
        log.warn("未授权访问被拒绝: {}", request.getRequestURI());  
                           
        // 设置响应内容类型和状态码  
        response.setContentType("application/json;charset=UTF-8");  
        response.setStatus(HttpStatus.UNAUTHORIZED.value());  
  
        // 创建人性化错误信息  
        Response<Void> errorResponse = new Response<>(  
                HttpStatus.UNAUTHORIZED.value(),  
                "访问被拒绝:请先登录获取访问权限",  
                null  
        );  
  
        // 将错误信息写入响应  
        response.getWriter().write(objectMapper.writeValueAsString(errorResponse));  
    }  
}

cors 跨域资源共享

它会在Filter链中添加一个CorsFilter。

.cors(cors -> cors.configurationSource(corsConfigurationSource()))
  • 配置顺序.cors() 必须放在其他安全配置(如 .csrf().authorizeHttpRequests())之前,否则跨域配置可能会被安全规则覆盖或失效。
  • 凭证冲突:当设置 configuration.setAllowCredentials(true) 时,allowedOrigins 绝对不能使用通配符 "*",必须明确指定具体的前端域名,否则浏览器会直接报错拦截4。
  • 预检请求放行:确保 allowedMethods 中包含了 "OPTIONS" 方法。如果自定义了拦截器,也要保证 OPTIONS 请求能正常到达 CORS 过滤器进行处理。
  • 完全覆盖性:一旦你在 Spring Security 中启用了 .cors(),它就会完全接管跨域处理,之前在 WebMvcConfigurer@CrossOrigin 注解中的相关配置将被忽略。
 /**
     * 定义全局 CORS 配置源
     */
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        // 允许的前端域名(生产环境强烈建议指定具体域名,而非 "*")
        configuration.setAllowedOrigins(Arrays.asList("https://frontend.example.com"));
        // 允许的 HTTP 方法(必须包含 OPTIONS 用于处理预检请求)
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
        // 允许的请求头
        configuration.setAllowedHeaders(Arrays.asList("Content-Type", "Authorization"));
        // 是否允许携带凭证(如 Cookie、JWT Token)
        configuration.setAllowCredentials(true);
        // 预检请求缓存时间(秒),减少 OPTIONS 请求频率
        configuration.setMaxAge(3600L); 

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

注意这里测试时遇到的坑,有的请求的Header中有Origin,有的没有,如果没有直接就放行了,这时就会发现好像配置没生效。什么时候有Origin呢?浏览器决定的。

在浏览器的安全沙箱机制下,JavaScript 代码是被禁止手动设置或修改 Origin 头的(它属于“Forbidden request header”)。这是为了防止恶意脚本伪造请求来源,从而破坏同源策略的安全防线。


原文链接:https://blog.dengwei.site/article/httpsecurity-various-configurations

posted @ 2026-06-06 13:26  衣来伸手饭来张口  阅读(29)  评论(0)    收藏  举报