java Swagger在Spring Security 6之后不起作用

nx7onnlm  于 2023-03-16  发布在  Java
关注(0)|答案(1)|浏览(137)

我一直在我所有的Sping Boot 应用程序中使用Swagger,在开始使用Spring Security的最新版本后,我意识到以前的配置似乎不起作用,并在尝试打开Swagger页面时抛出“*“需要完全身份验证才能访问此资源 *”错误。
以下是相关步骤。

**1.**添加maven依赖项:

<dependency>
   <groupId>io.springfox</groupId>
   <artifactId>springfox-boot-starter</artifactId>
   <version>3.0.0</version>
</dependency>

**2.**创建一个新类SwaggerConfig:

@Configuration
public class SwaggerConfig {

    private ApiInfo apiInfo() {
        return new ApiInfo(/* parameters */);
    }

    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.any())
                .build();
    }

}

**3.**向SecurityConfig添加必要的URL(注意,我使用requestMatchers是因为antMatchers已过时。

还要注意的是,我试图删除"/api/v1/auth/**",然后发现它是不允许的。这意味着,这种方法是允许AUTH_WHITELIST中的url。

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
@RequiredArgsConstructor
public class SecurityConfig {

    private final UserDetailsServiceImpl userDetailsService;

    private final AuthEntryPointJwt authEntryPointJwt;

    private static final String[] AUTH_WHITELIST = {
            "/api/v1/auth/**",

            // --- for Swagger UI v2
            "/v2/api-docs",
            "/swagger-resources",
            "/swagger-resources/**",
            "/configuration/ui",
            "/configuration/security",
            "/swagger-ui.html",
            "/webjars/**",

            // --- for Swagger UI v3
            "/v3/api-docs/**",
            "/swagger-ui/**"
    };

    // code omitted

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
            .cors().and()
            .csrf(csrf -> csrf.disable())
            .authorizeHttpRequests(auth -> auth
                .requestMatchers(AUTH_WHITELIST).permitAll()
                .anyRequest().authenticated()
            )
                .exceptionHandling().authenticationEntryPoint(
                     authEntryPointJwt).and()
                     .sessionManagement(sess -> sess.sessionCreationPolicy(
                     SessionCreationPolicy.STATELESS));

        httpSecurity.authenticationProvider(authenticationProvider());
        httpSecurity.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
        return httpSecurity.build();
    }
}

**4.**将以下变量添加到application.yml中:

spring:
  mvc:
    pathmatch:
      matching-strategy: ant_path_matcher
    throw-exception-if-no-handler-found: true

那么,这种实现有什么问题呢?

更新日期:

public class AuthTokenFilter extends OncePerRequestFilter {

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private UserDetailsServiceImpl userDetailsService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        try {
            String jwt = parseJwt(request);
            if (jwt != null && jwtUtils.validateJwtToken(jwt)) {
                String username = jwtUtils.getUserNameFromJwtToken(jwt);

                UserDetails userDetails = userDetailsService.loadUserByUsername(username);
                UsernamePasswordAuthenticationToken authentication =
                        new UsernamePasswordAuthenticationToken(
                                userDetails,
                                null,
                                userDetails.getAuthorities());
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        } catch (Exception e) {
            log.error(CANNOT_SET_AUTH, e);
        }
        filterChain.doFilter(request, response);
    }

    private String parseJwt(HttpServletRequest request) {
        String headerAuth = request.getHeader("Authorization");

        if (StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")) {
            return headerAuth.substring(7, headerAuth.length());
        }
        return null;
    }
}

日志:

2023-03-14 15:10:35.582 TRACE 29988 --- [nio-8080-exec-6] FilterChainProxy                         : Invoking ExceptionTranslationFilter (12/13)
2023-03-14 15:10:35.582 TRACE 29988 --- [nio-8080-exec-6] FilterChainProxy                         : Invoking AuthorizationFilter (13/13)
2023-03-14 15:10:35.582 TRACE 29988 --- [nio-8080-exec-6] estMatcherDelegatingAuthorizationManager : Authorizing SecurityContextHolderAwareRequestWrapper[ org.springframework.security.web.header.HeaderWriterFilter$HeaderWriterRequest@fa8b5ac]
2023-03-14 15:10:35.583 TRACE 29988 --- [nio-8080-exec-6] estMatcherDelegatingAuthorizationManager : Checking authorization on SecurityContextHolderAwareRequestWrapper[ org.springframework.security.web.header.HeaderWriterFilter$HeaderWriterRequest@fa8b5ac] using org.springframework.security.authorization.AuthenticatedAuthorizationManager@2e090619
2023-03-14 15:10:35.584 TRACE 29988 --- [nio-8080-exec-6] ExceptionTranslationFilter               : Sending AnonymousAuthenticationToken [Principal=anonymousUser, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=null], Granted Authorities=[ROLE_ANONYMOUS]] to authentication entry point since access is denied
org.springframework.security.access.AccessDeniedException: Access Denied
  at org.springframework.security.web.access.intercept.AuthorizationFilter.doFilter(AuthorizationFilter.java:98)
  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
  at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:126)
  at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:120)
  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
  at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:131)
  at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:85)
  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
  at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:100)
  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
  at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:179)
  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
  at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
  at com.github.security.AuthTokenFilter.doFilterInternal(AuthTokenFilter.java:56)
  at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
  at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:107)
  at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:93)
  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
  at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91)
  at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
  at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)
  at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)
  at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
  at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:82)
  at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:69)
  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
  at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:62)
  at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
  at org.springframework.security.web.session.DisableEncodeUrlFilter.doFilterInternal(DisableEncodeUrlFilter.java:42)
  at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
  at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:233)
  at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:191)
  at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:352)
  at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:268)
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
  at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
  at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
  at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
  at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
  at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
  at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
  at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:177)
  at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
  at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
  at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:119)
  at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
  at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
  at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
  at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:400)
  at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
  at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:859)
  at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1734)
  at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
  at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
  at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
  at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
  at java.base/java.lang.Thread.run(Thread.java:833)
2023-03-14 15:10:35.585 ERROR 29988 --- [nio-8080-exec-6] AuthEntryPointJwt                        : Unauthorized error: Full authentication is required to access this resource
2023-03-14 15:10:35.586 TRACE 29988 --- [nio-8080-exec-6] HstsHeaderWriter                         : Not injecting HSTS header since it did not match request to [Is Secure]
7gs2gvoe

7gs2gvoe1#

当我想对我的应用程序使用swagger时,我使用以下依赖项:

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

<dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
            <version>2.0.0</version>
</dependency>

并且在你的主类中添加@OpenAPIDefinition,跟在@SpringBootApplication后面。对我来说很有效,希望对你也一样。

相关问题