You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Security 6整合Swagger UI 3.0配置遇401错误求助

问题描述

把应用从Spring 2.7升级到Spring 3.1.2,需要配置Swagger UI 3.0和Spring Security 6。已经尝试用新的requestMatchers写法,但访问Swagger页面时一直报HTTP 401错误。以下是我的WebConfig代码片段:

package com.grammercetamol.securities.configurations;

import com.grammercetamol.implementation.UserDetailsServicesImpl;
import com.grammercetamol.securities.jwt.AuthFilter;
import com.grammercetamol.securities.jwt.JwtEntryPoint;
import com.grammercetamol.securities.passwordEncoder.PasswordEncrypt;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
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.configurers.AbstractHttpConfigurer;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import static org.springframework.security.config.http.SessionCreationPolicy.NEVER;

@Configuration
@EnableWebSecurity(debug = true)
@EnableMethodSecurity
@AllArgsConstructor
public class WebConfig {
    private static final String[] AUTH_WHITELIST = {
            "/api/v1/auth/**",
            "/v3/api-docs/**",
            "/v3/api-docs.yaml",
            "/swagger-ui/**",
            "/swagger-ui.html"
    };
    @Autowired
    private UserDetailsServicesImpl userDetailsServices;
    @Autowired
    private PasswordEncrypt passwordEncrypt;
    @Autowired
    private JwtEntryPoint entryPoint;

    @Autowired
    @Bean
    public AuthFilter filter() {
        return new AuthFilter();
    }

    public DaoAuthenticationProvider daoAuthenticationProvider() {
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        authenticationProvider.setUserDetailsService(userDetailsServices);
        authenticationProvider.setPasswordEncoder(passwordEncrypt.bCryptPasswordEncoder());
        return authenticationProvider;
    }

    @Bean
    public AuthenticationManager authenticationManager(
            AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .cors(AbstractHttpConfigurer::disable)
                .csrf(AbstractHttpConfigurer::disable);

        http
                .exceptionHandling(auth -> auth.authenticationEntryPoint(entryPoint));

        http
                .sessionManagement(auth -> auth.sessionCreationPolicy(NEVER));

        http
                .authorizeHttpRequests((requests) -> requests
                                .requestMatchers("/api/auth/**").permitAll()
                                .requestMatchers("/api/secured/**").permitAll()
                                .requestMatchers("/api/cloudinary/**").permitAll()
                                .requestMatchers("/api/v1/auth/**").permitAll()
                                .requestMatchers(AUTH_WHITELIST).permitAll()
                                .anyRequest().authenticated()
                );
        http
                .authenticationProvider(daoAuthenticationProvider());

        http
                .addFilterBefore(
                        filter(),
                        UsernamePasswordAuthenticationFilter.class
                );

        return http.build();
    }
}
解决方案

401问题的核心是Swagger相关路径没被正确放行,或者自定义JWT过滤器拦截了这些请求。结合你的代码,给出以下修正方案:

1. 简化并修正配置

把所有需要放行的路径统一管理,避免重复配置导致遗漏,同时优化注入方式:

@Configuration
@EnableWebSecurity(debug = true)
@EnableMethodSecurity
@AllArgsConstructor
public class WebConfig {
    // 把所有公开路径(含Swagger)统一放到白名单
    private static final String[] AUTH_WHITELIST = {
            // 认证接口
            "/api/auth/**",
            "/api/v1/auth/**",
            // 业务公开接口
            "/api/secured/**",
            "/api/cloudinary/**",
            // Swagger全量路径
            "/v3/api-docs/**",
            "/v3/api-docs.yaml",
            "/swagger-ui/**",
            "/swagger-ui.html"
    };

    // 用@AllArgsConstructor实现构造注入,去掉@Autowired字段
    private final UserDetailsServicesImpl userDetailsServices;
    private final PasswordEncrypt passwordEncrypt;
    private final JwtEntryPoint entryPoint;
    private final AuthFilter authFilter;

    @Bean
    public DaoAuthenticationProvider daoAuthenticationProvider() {
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        authenticationProvider.setUserDetailsService(userDetailsServices);
        authenticationProvider.setPasswordEncoder(passwordEncrypt.bCryptPasswordEncoder());
        return authenticationProvider;
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .cors(AbstractHttpConfigurer::disable)
                .csrf(AbstractHttpConfigurer::disable)
                .exceptionHandling(auth -> auth.authenticationEntryPoint(entryPoint))
                .sessionManagement(auth -> auth.sessionCreationPolicy(SessionCreationPolicy.NEVER))
                // 关键:直接用统一白名单放行所有公开路径
                .authorizeHttpRequests(requests -> requests
                        .requestMatchers(AUTH_WHITELIST).permitAll()
                        .anyRequest().authenticated()
                )
                .authenticationProvider(daoAuthenticationProvider())
                .addFilterBefore(authFilter, UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }
}

2. 检查自定义JWT过滤器

你的AuthFilter可能没跳过白名单路径,导致Swagger请求被拦截。给过滤器加个跳过逻辑:

public class AuthFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String requestPath = request.getRequestURI();
        AntPathMatcher pathMatcher = new AntPathMatcher();
        
        // 遍历白名单,匹配到就直接放行
        for (String whitePath : WebConfig.AUTH_WHITELIST) {
            if (pathMatcher.match(whitePath, requestPath)) {
                filterChain.doFilter(request, response);
                return;
            }
        }
        
        // 下面是原有JWT校验逻辑
        // ...
    }
}

3. 调试确认

开启了debug=true,启动后看控制台的路径匹配日志,确认Swagger的请求路径是否被归类到permitAll规则里。如果还有问题,打开浏览器开发者工具,看具体报401的请求路径,检查是否在白名单中。

内容的提问来源于stack exchange,提问作者Badmus Sodiq

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 22:47:31