Cómo configurar Spring Security para permitir el acceso a la URL de Swagger sin autenticación

92

Mi proyecto tiene Spring Security. Problema principal: no se puede acceder a la URL de swagger en http: // localhost: 8080 / api / v2 / api-docs . Dice el encabezado de autorización faltante o no válido.

Captura de pantalla de la ventana del navegador Mi pom.xml tiene las siguientes 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
fuente

Respuestas:

176

Agregar esto a su clase WebSecurityConfiguration debería ser suficiente.

@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
fuente
11
Si usa swagger-ui, necesita algo como esto: .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
En mi caso, esta regla 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
Se necesitaban más reglas: .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
¡Gracias por la respuesta! ¿Existe algún riesgo de seguridad al permitir el acceso a webjars / **?
ssimm
respuesta muy útil
Praveenkumar Beedanal
26

Actualicé con / configuration / ** y / swagger-resources / ** y funcionó para mí.

@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
fuente
¡Perfecto! Resuelto el problema.
Madhu
24

Tuve el mismo problema al usar Spring Boot 2.0.0.M7 + Spring Security + Springfox 2.8.0. Y resolví el problema usando la siguiente configuración de seguridad que permite el acceso público a los recursos de la IU de 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
fuente
2
después de agregar esta clase, puedo ver swagger-ui pero no se accede a las API a través del cartero incluso con access_token, obteniendo el error de acceso prohibido como se muestra a continuación,{ "timestamp": 1519798917075, "status": 403, "error": "Forbidden", "message": "Access Denied", "path": "/<some path>/shop" }
Chandrakant Audhutwar
@ChandrakantAudhutwar eliminar la antMatchers("/**").authenticated()declaración o reemplazarla con su propia configuración de autenticación. Tenga cuidado, es mejor que sepa lo que está haciendo con la seguridad.
naXa
sí, funcionó. Estaba pensando solo en omitir swagger-ui, pero otras API, ya que están protegidas. ahora mis API también se omiten.
Chandrakant Audhutwar
@ChandrakantAudhutwar, no es necesario copiar y pegar toda la SecurityConfigurationclase en su proyecto. Debe tener el suyo propio SecurityConfigurationdonde permita solicitudes a los recursos de la IU de Swagger y mantenga sus API seguras.
naXa
He AuthorizationServerConfigurerAdapterimplementado una clase que hace la autenticación de API.
Chandrakant Audhutwar
12

Para aquellos que usan una versión más nueva de 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
fuente
1
Nota: Si esto evita que obtenga un error "Se requiere autenticación", pero solo le muestra una página en blanco, también tuve que agregar "/ swagger-resources / **" y "/ swagger-resources" en esa lista y se solucionó es para mi.
Vinícius M
5

si su versión de Springfox superior a 2.5, debe agregar WebSecurityConfiguration como se muestra a continuación:

@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
fuente
duliu1990 tiene razón, desde springfox 2.5+, todos los recursos de springfox (swagger incluido) se han movido hacia abajo /swagger-resources. /v2/api-docses el punto final de la api swagger predeterminado (no tiene importancia con la interfaz de usuario), que se puede anular con la variable de configuración springfox.documentation.swagger.v2.path springfox
Mahieddine M. Ichir
3

Más o menos esta página tiene respuestas pero no todas están en un solo lugar. Estaba lidiando con el mismo problema y pasé bastante tiempo en él. Ahora tengo un mejor entendimiento y me gustaría compartirlo aquí:

Habilitando Swagger ui con Spring websecurity:

Si ha habilitado Spring Websecurity de forma predeterminada, bloqueará todas las solicitudes a su aplicación y devuelve 401. Sin embargo, para que la interfaz de usuario de swagger se cargue en el navegador, swagger-ui.html realiza varias llamadas para recopilar datos. La mejor manera de depurar es abrir swagger-ui.html en un navegador (como google chrome) y usar las opciones de desarrollador (tecla 'F12'). Puede ver varias llamadas realizadas cuando se carga la página y si swagger-ui no se carga por completo, probablemente algunas de ellas estén fallando.

es posible que deba decirle a Spring websecurity que ignore la autenticación para varios patrones de ruta de swagger. Estoy usando swagger-ui 2.9.2 y, en mi caso, a continuación se muestran los patrones que tuve que ignorar:

Sin embargo, si está utilizando una versión diferente, la suya podría cambiar. es posible que tenga que averiguar el suyo con la opción de desarrollador en su navegador como dije 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 con interceptor

Por lo general, es posible que no desee interceptar las solicitudes realizadas por swagger-ui.html. Para excluir varios patrones de arrogancia a continuación está el código:

La mayoría de los patrones de casos para la seguridad web y el interceptor serán los mismos.

@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/");
}

}

Dado que es posible que tenga que habilitar @EnableWebMvc para agregar interceptores, es posible que también deba agregar controladores de recursos a swagger similar a lo que he hecho en el fragmento de código anterior.

chanderdevx
fuente
¿Por qué está agregando /csrfexclusión?
Vishal
2

Limitando solo a los recursos relacionados con Swagger:

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

Aquí hay una solución completa para Swagger con Spring Security . Probablemente solo queramos habilitar Swagger en nuestro entorno de desarrollo y control de calidad y deshabilitarlo en el entorno de producción. Entonces, estoy usando una propiedad ( prop.swagger.enabled) como una bandera para omitir la autenticación de seguridad de primavera para swagger-ui solo en el entorno de desarrollo / 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
fuente
1

Estoy usando Spring Boot 5. Tengo este controlador que quiero que invoque un usuario no autenticado.

  //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();

Esto es lo que hice en la configuración.

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

Espero que esto ayude....

smac2020
fuente
0

Teniendo en cuenta todas sus solicitudes de API ubicadas con un patrón de URL /api/.., puede decirle a Spring que asegure solo este patrón de URL utilizando la siguiente configuración. Lo que significa que le está diciendo a Spring lo que debe asegurar en lugar de lo que debe 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
fuente
1
Gracias por este fragmento de código, que puede proporcionar una ayuda limitada a corto plazo. Una explicación adecuada mejoraría enormemente su valor a largo plazo al mostrar por qué es una buena solución al problema y lo haría más útil para futuros lectores con otras preguntas similares. Por favor, editar su respuesta a añadir un poco de explicación, incluyendo los supuestos realizados.
Toby Speight