Spring Boot中Swagger配置Bearer Token后未返回401 Unauthorized问题
问题解决:Spring Boot中Swagger配置Bearer Token后未返回401的原因及解决方案
你当前的Swagger配置只是在文档层面标记了接口需要Bearer Token认证,让Swagger UI显示锁图标,但并没有实际对接口开启权限校验——这就是不传Token调用接口时没返回401的核心原因。Swagger的@SecurityScheme和@SecurityRequirement仅用于生成API文档的认证说明,不会自动实现接口的权限拦截逻辑,必须配合Spring Security完成实际的Token验证。
解决方案步骤
1. 添加Spring Security依赖
在你的Gradle配置中加入Spring Security相关依赖:
implementation 'org.springframework.boot:spring-boot-starter-security' // 如果用标准JWT认证,需要添加这个依赖 implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server'
2. 配置Spring Security实现Token校验
创建Spring Security配置类,实现接口的权限拦截和Token验证逻辑。以下分两种场景给出示例:
场景一:标准JWT格式的Bearer Token
import org.springframework.context.annotation.Bean; 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.oauth2.jwt.JwtDecoder; import org.springframework.security.oauth2.jwt.NimbusJwtDecoder; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() // 允许Swagger相关路径无需认证,否则无法正常访问Swagger UI .antMatchers("/swagger-ui/**", "/v3/api-docs/**").permitAll() // 所有其他接口必须经过认证 .anyRequest().authenticated() .and() // 启用JWT格式的Bearer Token认证 .oauth2ResourceServer() .jwt(); } // 配置JWT解码器,根据实际密钥/认证方式调整 @Bean public JwtDecoder jwtDecoder() { // 示例:使用对称密钥,实际项目建议用非对称密钥或从配置文件读取密钥 String secret = "your-jwt-secret-key-here-1234567890"; SecretKey secretKey = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"); return NimbusJwtDecoder.withSecretKey(secretKey).build(); } }
场景二:自定义格式的Bearer Token
如果你的Token不是标准JWT,可通过自定义过滤器实现校验:
// 自定义Token过滤器 public class BearerTokenFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String authHeader = request.getHeader("Authorization"); if (authHeader != null && authHeader.startsWith("Bearer ")) { String token = authHeader.substring(7); // 这里替换为你的Token验证逻辑,比如从数据库/缓存校验有效性 boolean isValid = validateToken(token); if (!isValid) { response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); return; } // 验证通过后,设置认证信息到Security上下文 UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("current-user", null, Collections.emptyList()); SecurityContextHolder.getContext().setAuthentication(auth); } else { // 未携带Token时直接返回401 response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); return; } filterChain.doFilter(request, response); } private boolean validateToken(String token) { // 实现你的Token验证逻辑,比如校验签名、过期时间等 return true; } }
然后在SecurityConfig中注册该过滤器:
@Override protected void configure(HttpSecurity http) throws Exception { http.addFilterBefore(new BearerTokenFilter(), UsernamePasswordAuthenticationFilter.class) .csrf().disable() .authorizeRequests() .antMatchers("/swagger-ui/**", "/v3/api-docs/**").permitAll() .anyRequest().authenticated(); }
3. 保留原Swagger配置
你之前的SwaggerConfig和控制器上的@SecurityRequirement无需修改,它们负责让Swagger UI显示认证入口,用户输入Token后,Swagger会自动在请求头中携带Authorization: Bearer <token>,供Spring Security校验。
验证效果
重启项目后:
- 直接调用接口(不带Token)会返回
401 Unauthorized - 在Swagger UI中点击锁图标,输入你的Bearer Token,即可正常调用接口
内容的提问来源于stack exchange,提问作者MA-Dev
相关产品推荐
相关产品推荐

