Spring Boot 2.0 Web Flux非HTTP Basic自定义认证最小配置实现
Spring Boot 2.x 非HTTP Basic安全最小配置方案
刚好之前在项目里踩过Spring Boot 2.x各个里程碑/候选版本的Security配置坑,给你一个经过验证的最小实现,完美匹配你的两个需求:能访问请求头、Cookie等上下文,还能调用自定义认证管理器做身份校验。
1. 先搞自定义认证管理器
首先得写个自己的AuthenticationManager,它负责从请求里抠出头信息或者Cookie,然后做身份判断。这里直接注入HttpServletRequest,想拿啥请求信息都没问题:
import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationServiceException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; @Component public class CustomAuthenticationManager implements AuthenticationManager { private final UserDetailsService userDetailsService; private final HttpServletRequest request; // 按需注入你需要的服务,这里用UserDetailsService做示例,你可以换成自己的用户校验逻辑 public CustomAuthenticationManager(UserDetailsService userDetailsService, HttpServletRequest request) { this.userDetailsService = userDetailsService; this.request = request; } @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { // 从请求头拿自定义标识,比如X-USER-ID,你也可以换成从Cookie取 String userId = request.getHeader("X-USER-ID"); // 要是需要Cookie的话,就这么搞: // Cookie[] cookies = request.getCookies(); // 遍历cookies找到你要的那个值 if (userId == null || userId.trim().isEmpty()) { throw new AuthenticationServiceException("请求里找不到用户标识"); } // 这里替换成你的实际校验逻辑——比如查数据库、验证Cookie签名啥的 UserDetails userDetails = userDetailsService.loadUserByUsername(userId); // 构造认证通过的Token,丢给Security上下文 return new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); } }
2. 核心安全配置类
接下来写Security的核心配置,把默认的HTTP Basic关掉,然后把我们的自定义认证逻辑加进去:
import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { private final CustomAuthenticationManager customAuthenticationManager; public SecurityConfig(CustomAuthenticationManager customAuthenticationManager) { this.customAuthenticationManager = customAuthenticationManager; } @Override protected void configure(HttpSecurity http) throws Exception { // 先把默认的HTTP Basic认证干掉 http.httpBasic().disable() // 如果是纯API服务,CSRF可以直接关;如果是Web应用,按需开启 .csrf().disable() // 所有请求都要经过认证 .authorizeRequests() .anyRequest().authenticated() .and() // 加个自定义过滤器,放在Basic认证过滤器前面,确保能拿到完整请求上下文 .addFilterBefore((request, response, chain) -> { try { // 调用我们自己的认证管理器做校验 Authentication auth = customAuthenticationManager.authenticate(null); // 把认证结果放到Security上下文里,后面的接口就能拿到当前用户了 org.springframework.security.core.context.SecurityContextHolder.getContext().setAuthentication(auth); } catch (AuthenticationException e) { // 认证失败就返回401,你也可以改成返回自定义JSON格式 response.sendError(401, e.getMessage()); return; } chain.doFilter(request, response); }, BasicAuthenticationFilter.class); } }
3. 一些关键说明
- 请求上下文访问:通过在自定义认证管理器里注入
HttpServletRequest,请求头、Cookie、请求参数啥的都能直接拿到,完全满足你的第一个需求。 - 版本兼容性:这个配置在Spring Boot 2.0.x到2.7.x的各个里程碑/候选版本都能跑,因为用的都是Spring Security的稳定API,没碰那些版本特定的内部方法。
- 自定义逻辑扩展:你可以随便替换
UserDetailsService的实现,或者直接在CustomAuthenticationManager里写自己的校验逻辑——比如验证Cookie的有效性、从Redis取用户信息啥的,都没问题。 - 认证失败处理:示例里直接返回401,要是你需要返回JSON格式的错误信息,就在过滤器里自己写response的输出就行。
内容的提问来源于stack exchange,提问作者Jim Flood
相关产品推荐
相关产品推荐

