Jak skonfigurować Spring Security, aby umożliwić dostęp do adresu URL Swaggera bez uwierzytelniania

92

Mój projekt ma Spring Security. Główny problem: nie można uzyskać dostępu do swagger URL pod adresem http: // localhost: 8080 / api / v2 / api-docs . Mówi o brakującym lub nieprawidłowym nagłówku autoryzacji.

Zrzut ekranu okna przeglądarki Mój pom.xml zawiera następujące wpisy

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

Wpisy 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>

Konfiguracja 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
źródło

Odpowiedzi:

175

Dodanie tego do klasy WebSecurityConfiguration powinno załatwić sprawę.

@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
źródło
11
Jeśli używasz swagger-ui, potrzebujesz czegoś takiego: .antMatchers ("/ v2 / api-docs", "/ configuration / ui", "/ swagger-resources", "/ configuration / security", "/ swagger-ui .html "," / webjars / ** "," / swagger-resources / configuration / ui "," / swagger-ui.html "). allowAll ()
Daniel Martín
2
W moim przypadku ta reguła działa: .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"). allowAll ()
nikolai.serdiuk
6
Potrzeba więcej reguł: .antMatchers („/”, „/ csrf”, „/ v2 / api-docs”, „/ swagger-resources / configuration / ui”, „/ configuration / ui”, „/ swagger-resources”, "/ swagger-resources / configuration / security", "/ configuration / security", "/swagger-ui.html", "/ webjars / **"). allowAll ()
Mate Šimović
5
Dziękuję za odpowiedź! Czy istnieje zagrożenie bezpieczeństwa umożliwiające dostęp do plików WebJars / **?
ssimm
bardzo pomocna odpowiedź
Praveenkumar Beedanal
26

Zaktualizowałem / configuration / ** i / swagger-resources / ** i zadziałało.

@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
źródło
Idealny! Rozwiązany problem.
Madhu
24

Miałem ten sam problem podczas używania Spring Boot 2.0.0.M7 + Spring Security + Springfox 2.8.0. I rozwiązałem problem, używając następującej konfiguracji zabezpieczeń, która umożliwia publiczny dostęp do zasobów interfejsu użytkownika Swaggera.

@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
źródło
2
po dodaniu tej klasy mogę zobaczyć swagger-ui, ale API nie są dostępne przez listonosza nawet z access_token, uzyskując błąd zakazu dostępu, jak poniżej,{ "timestamp": 1519798917075, "status": 403, "error": "Forbidden", "message": "Access Denied", "path": "/<some path>/shop" }
Chandrakant Audhutwar
@ChandrakantAudhutwar usuń antMatchers("/**").authenticated()instrukcję lub zamień na własną konfigurację uwierzytelniania. Uważaj, lepiej wiedz, co robisz z bezpieczeństwem.
naXa
tak, zadziałało. Myślałem tylko o ominięciu swagger-ui, ale innych API, które są zabezpieczone. teraz moje interfejsy API są również pomijane.
Chandrakant Audhutwar
@ChandrakantAudhutwar nie musisz kopiować i wklejać całej SecurityConfigurationklasy do swojego projektu. Powinieneś mieć swój własny, w SecurityConfigurationktórym zezwalasz na żądania do zasobów interfejsu użytkownika Swagger i zabezpieczasz swoje interfejsy API.
naXa
Mam AuthorizationServerConfigurerAdapterrealizowane klasy co sprawia uwierzytelniania API.
Chandrakant Audhutwar
12

Dla tych, którzy używają nowszej wersji 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
źródło
1
Uwaga: jeśli to powstrzymuje Cię przed wyświetleniem błędu „Wymagane uwierzytelnienie”, ale pokazuje tylko pustą stronę, musiałem również dodać „/ swagger-resources / **” i „/ swagger-resources” na tej liście i to naprawiono to dla mnie.
Vinícius M
5

jeśli twoja wersja springfox wyższa niż 2.5 , powinna zostać dodana do WebSecurityConfiguration jak poniżej:

@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
źródło
duliu1990 ma rację, ponieważ od springfox 2.5+ wszystkie zasoby Springfox (w tym swagger) zostały obniżone /swagger-resources. /v2/api-docsjest punktem końcowym domyślny puszyć API (nie dotyczą z UI), które mogą być nadpisane przy zmiennej config springfox.documentation.swagger.v2.path springfox
Mahieddine M. Ichir
3

Mniej więcej ta strona zawiera odpowiedzi, ale nie wszystkie są w jednym miejscu. Miałem do czynienia z tym samym problemem i spędziłem nad tym całkiem sporo czasu. Teraz lepiej rozumiem i chciałbym się tym podzielić tutaj:

I Włączanie interfejsu Swagger z zabezpieczeniem sieci Spring:

Jeśli domyślnie włączyłeś Spring Websecurity, zablokuje ono wszystkie żądania do Twojej aplikacji i zwróci 401. Jednakże, aby interfejs swagger załadował się w przeglądarce, swagger-ui.html wykonuje kilka wywołań w celu zebrania danych. Najlepszym sposobem debugowania jest otwarcie pliku swagger-ui.html w przeglądarce (np. Google Chrome) i użycie opcji programisty (klawisz „F12”). Możesz zobaczyć kilka wywołań wykonanych, gdy strona się ładuje, a jeśli swagger-ui nie ładuje się całkowicie, prawdopodobnie niektóre z nich zawodzą.

może być konieczne poinformowanie Spring websecurity, aby ignorowało uwierzytelnianie dla kilku wzorców ścieżek swagger. Używam swagger-ui 2.9.2 iw moim przypadku poniżej znajdują się wzorce, które musiałem zignorować:

Jeśli jednak używasz innej wersji, Twoja może się zmienić. być może będziesz musiał wymyślić swoją za pomocą opcji programisty w przeglądarce, jak powiedziałem wcześniej.

@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 Włączanie swagger ui z interceptorem

Generalnie możesz nie chcieć przechwytywać żądań wysyłanych przez swagger-ui.html. Aby wykluczyć kilka wzorców dumy poniżej, jest kod:

W większości przypadków wzorzec bezpieczeństwa sieci i przechwytywacza będzie taki sam.

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

}

Ponieważ być może będziesz musiał włączyć @EnableWebMvc, aby dodać przechwytywacze, być może będziesz musiał dodać programy obsługi zasobów do swagger, podobnie jak to zrobiłem w powyższym fragmencie kodu.

chanderdevx
źródło
Dlaczego dodajesz /csrfwykluczenie?
Vishal
2

Ograniczając się tylko do zasobów związanych ze Swaggerem:

.antMatchers("/v2/api-docs", "/swagger-resources/**", "/swagger-ui.html", "/webjars/springfox-swagger-ui/**");
m52509791
źródło
2

Oto kompletne rozwiązanie dla Swagger z Spring Security . Prawdopodobnie chcemy włączyć Swagger tylko w naszym środowisku programistycznym i QA i wyłączyć go w środowisku produkcyjnym. Tak więc używam property ( prop.swagger.enabled) jako flagi, aby ominąć uwierzytelnianie zabezpieczeń wiosny dla swagger-ui tylko w środowisku programistycznym / 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
źródło
1

Używam Spring Boot 5. Mam ten kontroler, który powinien wywołać nieuwierzytelniony użytkownik.

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

Oto, co zrobiłem w konfiguracji.

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

Mam nadzieję że to pomoże....

smac2020
źródło
0

Biorąc pod uwagę wszystkie żądania API, które znajdują się we wzorcu adresu URL /api/.., możesz powiedzieć Springowi, aby zabezpieczył tylko ten wzorzec adresu URL, używając poniższej konfiguracji. Co oznacza, że ​​mówisz wiosny, co ma zabezpieczyć, a nie co zignorować.

@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
źródło
1
Dziękujemy za ten fragment kodu, który może zapewnić ograniczoną krótkoterminową pomoc. Właściwe wyjaśnienie znacznie poprawiłoby jego długoterminową wartość, pokazując, dlaczego jest to dobre rozwiązanie problemu i uczyniłoby go bardziej użytecznym dla przyszłych czytelników z innymi, podobnymi pytaniami. Proszę edytować swoją odpowiedź dodać kilka wyjaśnień, w tym założeń już wykonanych.
Toby Speight