Доступ к Springfox локальный пользовательский интерфейс swagger запускает HttpServletRequests

#java #spring #http #swagger

#java #spring #http #swagger

Вопрос:

У меня есть проект spring boot с некоторыми конечными точками rest и страницей пользовательского интерфейса swagger. Я могу успешно получить доступ к странице swagger по адресу http://localhost:8080/swagger-ui.html #/ с помощью springfox-swagger-ui и springfox-swagger2 2.9.2 (или в http://localhost:8080/swagger-ui / при использовании springfox-boot-starter 3.0.0). В рамках моей конфигурации безопасности у меня есть простой фильтр аутентификации, который можно использовать для проверки ключей api, которые пользователь сможет ввести на странице swagger.

Однако моя проблема в том, что каждый раз, когда я захожу на страницу swagger, она автоматически вызывает метод attemptAuthentication() в моем фильтре (и несколько раз). Этого не должно произойти. Он должен вызываться только тогда, когда я ввожу ключевую информацию, а затем нажимаю авторизовать на странице.

HttpServletRequest, пытающийся выполнить аутентификацию, имеет один и тот же тип для всех 10 запросов. Все запускаемые запросы поступают на разные URI. Это тип запроса

 SecurityContextHolderAwareRequestWrapper[org.springframework.security.web.header.HeaderWriterFilter$HeaderWriterRequest]
 

И это все URI:

/swagger-ui/

/swagger-ui/springfox.css

/swagger-ui/swagger-ui.css

/swagger-ui/swagger-ui-bundle.js

/swagger-ui/swagger-ui-standalone-preset.js

/swagger-ui/springfox.js

/swagger-ресурсы / конфигурация / пользовательский интерфейс

/swagger-ресурсы / конфигурация / безопасность

/swagger-ресурсы

/v2/api-docs

SimpleAuthFilter

 public class SimpleAuthFilter extends AbstractAuthenticationProcessingFilter {

  public SimpleAuthFilter(final RequestMatcher req) {
    super(req)
    setAuthenticationManager(new MyAuthManager())
  }

  @Override
  public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res) {
    // -> Getting called here when visting swagger page
  }

  @Override
  protected void successfulAuthentication(final HttpServletRequest req, final HttpServletResponse, final FilterChain chain, final Authentication auth) throws IOException, ServletException {
    SecurityContextHolder.getContext().setAuthentication(auth);
    chain.doFilter(req, res);
  }
}
 

MyAuthManager

 private class MyAuthManager implements AuthenticationManager {
    @Override
    public Authentication authenticate(Authentication auth) throws AuthenticationException {
        throw new AuthenticationServiceException("Bad auth");
    }
}
 

MySecurityConfig

 @Configuration
@EnableWebSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
  @Override
  public void configure(HttpSecurity sec) throws Exception {
        http.sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .addFilterBefore(filter(), AnonymousAuthenticationFilter.class)
            .authorizeRequests()
            ...
            ;
  }

  @Bean
  public SimpleAuthFilter filter() {
    RequestMatcher match = new OrRequestMatcher(new AntPathRequestMatcher("/**"));
    return new SimpleAuthFilter(match);
  }
}
 

SwaggerConfiguration

 @Configuration
@EnableSwagger2
public class SwaggerConfiguration {
  @Bean
  public Docket api() {
    return new Docket(DocumentationType.SWAGGER_2)
            .select()
            .apis(RequestHandlerSelectors.basePackage("MyProject"))
            .paths(PathSelectors.any())
            .build()
            .enableUrlTemplating(true)
            .securitySchemes(Collections.singleton(new ApiKey("mykey", "Authorization", "header")))
            .securityContexts(Collections.singleton(context()));
  }
  
  public SecurityContext context() {
    return SecurityContext.builder()
             .securityReferences(securityReferences())
             .forPaths(PathSelectors.any())
             .build();
  }

  public List<SecurityReference> securityReferences() {
    return Collections.singletonList(new SecurityReference("mykey", new AuthorizationScope[]{new AuthorizationScope("global", "accessEverything")}));
  }
}
 

Я думал, что проблема может быть связана с необходимостью настройки обработчиков ресурсов путем расширения WebMvcConfigurationSupport, но каждый раз, когда я пытался, на странице swagger возникали проблемы. Или мне может понадобиться как-то исключить эти пути URI с помощью нескольких antMatcher() ?

Я пробовал использовать разные зависимости swagger, перемещая местоположение фильтра в конфигурации HttpSecurity, обработчики ресурсов, контроллеры просмотра, но у меня ничего не получилось.

Я использую spring-boot-starter-web, spring-boot-starter-security 2.3.4 и spring-boot-starter-validation 2.4.0

Ответ №1:

Я выяснил частичный ответ, который заключается в том, что RequestMatcher, используемый для создания фильтра в MySecurityConfig, вместо этого должен быть специфичным ТОЛЬКО для конечных точек, а не быть /** , что приведет к тому, что фильтр фактически попытается выполнить аутентификацию даже при посещении страницы swagger.

Проблема с использованием AntPathRequestMatcher заключается в том, что мои конечные точки не имеют шаблона с префиксом, например,

/endpoint1

/endpoint2