Como configurar o Spring Security para permitir que o URL do Swagger seja acessado sem autenticação

97

Meu projeto tem Spring Security. Problema principal: Não é possível acessar o URL swagger em http: // localhost: 8080 / api / v2 / api-docs . Ele diz Cabeçalho de autorização ausente ou inválido.

Captura de tela da janela do navegador Meu pom.xml contém as seguintes entradas

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.4.0</version>
</dependency>

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.4.0</version>
</dependency>

SwaggerConfig:

@Configuration
@EnableSwagger2
public class SwaggerConfig {

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

private ApiInfo apiInfo() {
    ApiInfo apiInfo = new ApiInfo("My REST API", "Some custom description of API.", "API TOS", "Terms of service", "[email protected]", "License of API", "API license URL");
    return apiInfo;
}

AppConfig:

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "com.musigma.esp2" })
@Import(SwaggerConfig.class)
public class AppConfig extends WebMvcConfigurerAdapter {

// ========= Overrides ===========

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new LocaleChangeInterceptor());
}

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("swagger-ui.html")
      .addResourceLocations("classpath:/META-INF/resources/");

    registry.addResourceHandler("/webjars/**")
      .addResourceLocations("classpath:/META-INF/resources/webjars/");
}

Entradas web.xml:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        com.musigma.esp2.configuration.AppConfig
        com.musigma.esp2.configuration.WebSecurityConfiguration
        com.musigma.esp2.configuration.PersistenceConfig
        com.musigma.esp2.configuration.ACLConfig
        com.musigma.esp2.configuration.SwaggerConfig
    </param-value>
</context-param>

WebSecurityConfig:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@ComponentScan(basePackages = { "com.musigma.esp2.service", "com.musigma.esp2.security" })
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
        .csrf()
            .disable()
        .exceptionHandling()
            .authenticationEntryPoint(this.unauthorizedHandler)
            .and()
        .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
        .authorizeRequests()
            .antMatchers("/auth/login", "/auth/logout").permitAll()
            .antMatchers("/api/**").authenticated()
            .anyRequest().authenticated();

        // custom JSON based authentication by POST of {"username":"<name>","password":"<password>"} which sets the token header upon authentication
        httpSecurity.addFilterBefore(loginFilter(), UsernamePasswordAuthenticationFilter.class);

        // custom Token based authentication based on the header previously given to the client
        httpSecurity.addFilterBefore(new StatelessTokenAuthenticationFilter(tokenAuthenticationService), UsernamePasswordAuthenticationFilter.class);
    }
}
shubhendu_shekhar
fonte

Respostas:

180

Adicionar isso à sua classe WebSecurityConfiguration deve resolver o problema.

@Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/v2/api-docs",
                                   "/configuration/ui",
                                   "/swagger-resources/**",
                                   "/configuration/security",
                                   "/swagger-ui.html",
                                   "/webjars/**");
    }

}
Stijn Maller
fonte
11
Se você usar o swagger-ui, você precisará de algo como isto: .antMatchers ("/ v2 / api-docs", "/ configuration / ui", "/ swagger-resources", "/ configuration / security", "/ swagger-ui .html "," / webjars / ** "," / swagger-resources / configuration / ui "," / swagger-ui.html "). permitAll ()
Daniel Martín
2
No meu caso, esta regra está funcionando: .antMatchers ("/ v2 / api-docs", "/ configuration / ui", "/ swagger-resources", "/ configuration / security", "/swagger-ui.html", "/ webjars / **", "/ swagger-resources / configuration / ui", "/ swagge‌ r-ui.html", "/ swagger-resources / configuration / security"). permitAll ()
nikolai.serdiuk
6
Mais regras necessárias: .antMatchers ("/", "/ csrf", "/ v2 / api-docs", "/ swagger-resources / configuration / ui", "/ configuration / ui", "/ swagger-resources", "/ swagger-resources / configuration / security", "/ configuration / security", "/swagger-ui.html", "/ webjars / **"). permitAll ()
Mate Šimović
5
Obrigado pela resposta! Existe algum risco de segurança ao permitir o acesso a webjars / **?
ssimm
resposta muito útil
Praveenkumar Beedanal 01 de
26

Eu atualizei com / configuration / ** e / swagger-resources / ** e funcionou para mim.

@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers("/v2/api-docs", "/configuration/ui", "/swagger-resources/**", "/configuration/**", "/swagger-ui.html", "/webjars/**");

}
Akshata Suvarna
fonte
Perfeito! Resolvido o problema.
Madhu
25

Eu tive o mesmo problema ao usar Spring Boot 2.0.0.M7 + Spring Security + Springfox 2.8.0. E resolvi o problema usando a seguinte configuração de segurança que permite o acesso público aos recursos da IU do Swagger.

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    private static final String[] AUTH_WHITELIST = {
            // -- swagger ui
            "/v2/api-docs",
            "/swagger-resources",
            "/swagger-resources/**",
            "/configuration/ui",
            "/configuration/security",
            "/swagger-ui.html",
            "/webjars/**"
            // other public endpoints of your API may be appended to this array
    };


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.
                // ... here goes your custom security configuration
                authorizeRequests().
                antMatchers(AUTH_WHITELIST).permitAll().  // whitelist Swagger UI resources
                // ... here goes your custom security configuration
                antMatchers("/**").authenticated();  // require authentication for any endpoint that's not whitelisted
    }

}
naXa
fonte
2
depois de adicionar esta classe, posso ver o swagger-ui, mas as APIs não são acessadas via carteiro mesmo com access_token, obtendo o erro de acesso proibido conforme abaixo,{ "timestamp": 1519798917075, "status": 403, "error": "Forbidden", "message": "Access Denied", "path": "/<some path>/shop" }
Chandrakant Audhutwar
@ChandrakantAudhutwar delete a antMatchers("/**").authenticated()instrução ou substitua por sua própria configuração de autenticação. Cuidado, é melhor você saber o que está fazendo com segurança.
naXa
sim, funcionou. Eu estava pensando em apenas ignorar o swagger-ui, mas outras APIs, pois é seguro. agora minhas APIs também são ignoradas.
Chandrakant Audhutwar
@ChandrakantAudhutwar você não precisa copiar e colar a SecurityConfigurationclasse inteira em seu projeto. Você deve ter seu próprio, SecurityConfigurationonde permitir solicitações para recursos de IU do Swagger e manter suas APIs seguras.
naXa
Eu AuthorizationServerConfigurerAdapterimplementei uma classe que faz a autenticação da API.
Chandrakant Audhutwar
14

Para aqueles que usam uma versão mais recente do swagger 3 org.springdoc:springdoc-openapi-ui

@Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/v3/api-docs/**", "/swagger-ui.html", "/swagger-ui/**");
    }
}
Dennis Glot
fonte
2
Observação: se isso impedisse que você recebesse um erro "Autenticação necessária", mas apenas mostrasse uma página em branco, também tive que adicionar "/ swagger-resources / **" e "/ swagger-resources" nessa lista e corrigiu isso para mim.
Vinícius M
6

se a sua versão springfox superior a 2.5, deve ser adicionado WebSecurityConfiguration como abaixo:

@Override
public void configure(HttpSecurity http) throws Exception {
    // TODO Auto-generated method stub
    http.authorizeRequests()
        .antMatchers("/v2/api-docs", "/swagger-resources/configuration/ui", "/swagger-resources", "/swagger-resources/configuration/security", "/swagger-ui.html", "/webjars/**").permitAll()
        .and()
        .authorizeRequests()
        .anyRequest()
        .authenticated()
        .and()
        .csrf().disable();
}
duliu1990
fonte
duliu1990 está certo, desde o springfox 2.5+, todos os recursos do springfox (swagger incluído) foram movidos /swagger-resources. /v2/api-docsé o ponto de extremidade de api swagger padrão (sem preocupação com a IU), que pode ser substituído pela variável de configuração springfox.documentation.swagger.v2.path springfox
Mahieddine M. Ichir
4

Mais ou menos esta página tem respostas, mas nem todas estão no mesmo lugar. Eu estava lidando com o mesmo problema e gastei um bom tempo nisso. Agora compreendo melhor e gostaria de compartilhar aqui:

I Habilitando Swagger ui com Spring websecurity:

Se você habilitou o Spring Websecurity por padrão, ele bloqueará todas as solicitações do seu aplicativo e retornará 401. No entanto, para que o swagger ui seja carregado no navegador, swagger-ui.html faz várias chamadas para coletar dados. A melhor maneira de depurar é abrir swagger-ui.html em um navegador (como o google chrome) e usar as opções do desenvolvedor (tecla 'F12'). Você pode ver várias chamadas feitas quando a página carrega e se o swagger-ui não estiver carregando completamente, provavelmente algumas delas estão falhando.

você pode precisar dizer ao Spring websecurity para ignorar a autenticação para vários padrões de caminho swagger. Estou usando o swagger-ui 2.9.2 e, no meu caso, abaixo estão os padrões que tive que ignorar:

No entanto, se você estiver usando uma versão diferente, a sua pode mudar. você pode ter que descobrir o seu com a opção de desenvolvedor em seu navegador, como eu disse antes.

@Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers("/v2/api-docs", "/configuration/ui", 
            "/swagger-resources/**", "/configuration/**", "/swagger-ui.html"
            , "/webjars/**", "/csrf", "/");
}
}

II Habilitando swagger ui com interceptor

Geralmente, você não pode querer interceptar solicitações feitas por swagger-ui.html. Para excluir vários padrões de arrogância abaixo está o código:

A maioria dos casos padrão para segurança da web e interceptor será o mesmo.

@Configuration
@EnableWebMvc
public class RetrieveCiamInterceptorConfiguration implements WebMvcConfigurer {

@Autowired
RetrieveInterceptor validationInterceptor;

@Override
public void addInterceptors(InterceptorRegistry registry) {

    registry.addInterceptor(validationInterceptor).addPathPatterns("/**")
    .excludePathPatterns("/v2/api-docs", "/configuration/ui", 
            "/swagger-resources/**", "/configuration/**", "/swagger-ui.html"
            , "/webjars/**", "/csrf", "/");
}

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("swagger-ui.html")
      .addResourceLocations("classpath:/META-INF/resources/");

    registry.addResourceHandler("/webjars/**")
      .addResourceLocations("classpath:/META-INF/resources/webjars/");
}

}

Já que você pode ter que habilitar @EnableWebMvc para adicionar interceptores, você também pode ter que adicionar manipuladores de recursos para swagger semelhante ao que fiz no trecho de código acima.

Chanderdevx
fonte
Por que você está adicionando /csrfexclusão?
Vishal
2

Limitando apenas a recursos relacionados ao Swagger:

.antMatchers("/v2/api-docs", "/swagger-resources/**", "/swagger-ui.html", "/webjars/springfox-swagger-ui/**");
m52509791
fonte
2

Aqui está uma solução completa para Swagger com Spring Security . Provavelmente, queremos ativar o Swagger apenas em nosso ambiente de desenvolvimento e controle de qualidade e desativá-lo no ambiente de produção. Portanto, estou usando um property ( prop.swagger.enabled) como um sinalizador para ignorar a autenticação de segurança do spring para swagger-ui apenas no ambiente de desenvolvimento / qa.

@Configuration
@EnableSwagger2
public class SwaggerConfiguration extends WebSecurityConfigurerAdapter implements WebMvcConfigurer {

@Value("${prop.swagger.enabled:false}")
private boolean enableSwagger;

@Bean
public Docket SwaggerConfig() {
    return new Docket(DocumentationType.SWAGGER_2)
            .enable(enableSwagger)
            .select()
            .apis(RequestHandlerSelectors.basePackage("com.your.controller"))
            .paths(PathSelectors.any())
            .build();
}

@Override
public void configure(WebSecurity web) throws Exception {
    if (enableSwagger)  
        web.ignoring().antMatchers("/v2/api-docs",
                               "/configuration/ui",
                               "/swagger-resources/**",
                               "/configuration/security",
                               "/swagger-ui.html",
                               "/webjars/**");
}

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    if (enableSwagger) {
        registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
    }
  }
}
Abdul Rahman
fonte
1

Estou usando o Spring Boot 5. Tenho este controlador que desejo que um usuário não autenticado invoque.

  //Builds a form to send to devices   
@RequestMapping(value = "/{id}/ViewFormit", method = RequestMethod.GET)
@ResponseBody
String doFormIT(@PathVariable String id) {
    try
    {
        //Get a list of forms applicable to the current user
        FormService parent = new FormService();

Aqui está o que eu fiz na configuração.

  @Override
   protected void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
            .antMatchers(
                    "/registration**",
                    "/{^[\\\\d]$}/ViewFormit",

Espero que isto ajude....

smac2020
fonte
1

Alguma configuração de segurança e você está pronto com arrogância aberta para todos

Para Swagger V2

@Configuration
@EnableWebSecurity
public class CabSecurityConfig extends WebSecurityConfigurerAdapter {


    private static final String[] AUTH_WHITELIST = {
            // -- swagger ui
            "/v2/api-docs", 
            "/swagger-resources/**", 
            "/configuration/ui",
            "/configuration/security", 
            "/swagger-ui.html",
            "/webjars/**"
    };

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        // ... here goes your custom security configuration
        http.authorizeRequests().
        antMatchers(AUTH_WHITELIST).permitAll(). // whitelist URL permitted
        antMatchers("/**").authenticated(); // others need auth
    }

}

Para Swagger V3

@Configuration
@EnableWebSecurity
public class CabSecurityConfig extends WebSecurityConfigurerAdapter {


    private static final String[] AUTH_WHITELIST = {
            // -- swagger ui
            "/v2/api-docs",
            "/v3/api-docs",  
            "/swagger-resources/**", 
            "/swagger-ui/**",
             };

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        // ... here goes your custom security configuration
        http.authorizeRequests().
        antMatchers(AUTH_WHITELIST).permitAll(). // whitelist URL permitted
        antMatchers("/**").authenticated(); // others need auth
    }

}
Rupesh Kumar
fonte
0

Considerando todas as suas solicitações de API localizadas com um padrão de url de, /api/..você pode dizer ao Spring para proteger apenas esse padrão de url usando a configuração abaixo. O que significa que você está dizendo a spring o que proteger em vez do que ignorar.

@Override
protected void configure(HttpSecurity http) throws Exception {
  http
    .csrf().disable()
     .authorizeRequests()
      .antMatchers("/api/**").authenticated()
      .anyRequest().permitAll()
      .and()
    .httpBasic().and()
    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
Siddu
fonte
1
Obrigado por este trecho de código, que pode fornecer alguma ajuda limitada de curto prazo. Uma explicação adequada melhoraria muito seu valor a longo prazo, mostrando por que essa é uma boa solução para o problema, e a tornaria mais útil para futuros leitores com outras questões semelhantes. Por favor edite sua resposta para adicionar alguma explicação, incluindo as suposições que você fez.
Toby Speight,