Як налаштувати Spring Security, щоб дозволити доступ до URL-адреси Swagger без автентифікації


92

Мій проект має Spring Security. Основна проблема: Не вдалося отримати доступ до URL-адреси, що розміщується, за адресою http: // localhost: 8080 / api / v2 / api-docs . Там написано Заголовок авторизації відсутній або недійсний.

Знімок екрана вікна браузера Мій pom.xml містить такі записи

<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", "myeaddress@company.com", "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/");
}

Записи 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);
    }
}

Відповіді:


176

Додавання цього до вашого класу WebSecurityConfiguration має зробити трюк.

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

}

11
Якщо ви використовуєте swagger-ui, вам потрібно щось на зразок цього: .antMatchers ("/ v2 / api-docs", "/ configuration / ui", "/ swagger-resources", "/ configuration / security", "/ swagger-ui .html "," / webjars / ** "," / swagger-resources / configuration / ui "," / swagger-ui.html "). allowAll ()
Даніель Мартін,

2
У моєму випадку це правило працює: .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
Потрібно більше правил: .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
Дякую за відповідь! Чи існує ризик безпеки, що дозволяє доступ до webjars / **?
ssimm

дуже корисна відповідь
Praveenkumar Beedanal

26

Я оновився за допомогою / configuration / ** та / swagger-resources / **, і це працювало для мене.

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

}

Ідеально! Вирішив питання.
Мадху

24

У мене була та сама проблема при використанні Spring Boot 2.0.0.M7 + Spring Security + Springfox 2.8.0. І я вирішив проблему, використовуючи наведену нижче конфігурацію безпеки, яка дозволяє загальнодоступний доступ до ресурсів інтерфейсу 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
    }

}

2
після додавання цього класу я бачу swagger-ui, але API не отримує доступ через листоношу навіть з access_token, отримуючи заборонену помилку, як { "timestamp": 1519798917075, "status": 403, "error": "Forbidden", "message": "Access Denied", "path": "/<some path>/shop" }
показано

@ChandrakantAudhutwar видалити antMatchers("/**").authenticated()заяву або замінити власною конфігурацією автентифікації. Будьте обережні, вам краще знати, що ви робите з безпекою.
naXa

так, це спрацювало. Я думав лише обходити swagger-ui, але інші API, оскільки це захищено. тепер мої API також обійшли.
Чандракант Аудхутвар,

@ChandrakantAudhutwar, вам не потрібно копіювати весь SecurityConfigurationклас до вашого проекту. Ви повинні мати свій власний, SecurityConfigurationде ви дозволяєте запити на ресурси інтерфейсу Swagger та захищаєте свої API.
naXa

Я AuthorizationServerConfigurerAdapterреалізував клас, який робить автентифікацію API.
Чандракант Аудхватвар,

13

Для тих, хто використовує новішу версію 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/**");
    }
}

2
Примітка. Якщо це заважає отримувати помилку "Потрібна автентифікація", а просто показує порожню сторінку, мені також довелося додати "/ swagger-resources / **" та "/ swagger-resources" у цей список, і це виправлено це для мене.
Vinícius M

5

якщо ваша версія Springfox вище 2,5 ,, слід додати WebSecurityConfiguration, як показано нижче:

@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 має рацію, оскільки з springfox 2.5+ усі ресурси springfox (включаючи обману) переїхали /swagger-resources. /v2/api-docsце чванство по замовчуванням апі кінцевій точці (не стосується з UI), який може бути перевизначений зі змінною конфігурації springfox.documentation.swagger.v2.path springfox
Mahieddine М. Ichir

3

Більш-менш на цій сторінці є відповіді, але всі вони не в одному місці. Я мав справу з тим самим питанням і проводив на ньому досить добрий час. Тепер я краще зрозумів і хотів би поділитися цим тут:

I Увімкнення інтерфейсу Swagger з Spring websecurity:

Якщо ви за замовчуванням увімкнули Spring Websecurity, він заблокує всі запити до вашої програми і поверне 401. Однак для завантаження користувацького інтерфейсу swagger-браузера swagger-ui.html робить кілька дзвінків для збору даних. Найкращий спосіб налагодження - це відкрити swagger-ui.html у браузері (наприклад, google chrome) та скористатися параметрами розробника (клавіша 'F12'). Ви можете побачити кілька дзвінків, здійснених під час завантаження сторінки, і якщо користувальницький інтерфейс не завантажується повністю, можливо, деякі з них не працюють.

можливо, вам доведеться сказати Spring websecurity ігнорувати автентифікацію для декількох шаблонів шляхів обміну. Я використовую swagger-ui 2.9.2, і в моєму випадку нижче є шаблони, які мені довелося ігнорувати:

Однак якщо ви використовуєте іншу версію, ваша версія може змінитися. можливо, вам доведеться розібратися зі своїм варіантом розробника у вашому браузері, як я вже говорив раніше.

@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 Увімкнення користувальницького інтерфейсу з перехоплювачем

Як правило, ви не хочете перехоплювати запити, зроблені за допомогою swagger-ui.html. Нижче наведено код для виключення декількох моделей хитрості:

Більшість випадків для веб-безпеки та перехоплювача будуть однаковими.

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

}

Оскільки вам, можливо, доведеться ввімкнути @EnableWebMvc для додавання перехоплювачів, вам також може знадобитися додати обробники ресурсів для обміну, як це було зроблено у наведеному вище фрагменті коду.


Чому ви додаєте /csrfвиключення?
Vishal

2

Обмежуючись лише ресурсами, пов'язаними з Swagger:

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

2

Ось повне рішення для Swagger з Spring Security . Можливо, ми хочемо увімкнути Swagger лише в нашому середовищі розробки та контролю якості та відключити його у виробничому середовищі. Отже, я використовую властивість ( prop.swagger.enabled) як прапор для обходу весняної автентифікації безпеки для swagger-ui лише в середовищі development / 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/");
    }
  }
}

1

Я використовую Spring Boot 5. У мене є цей контролер, який я хочу, щоб неавторизований користувач викликав.

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

Ось що я зробив у конфігурації.

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

Сподіваюся, це допомагає ....


0

Враховуючи всі ваші запити API, розташовані з шаблоном URL-адреси, /api/..ви можете сказати Spring, щоб захистити лише цей шаблон URL-адреси, використовуючи налаштування нижче. А це означає, що ви говорите весні, що захистити, а не ігнорувати.

@Override
protected void configure(HttpSecurity http) throws Exception {
  http
    .csrf().disable()
     .authorizeRequests()
      .antMatchers("/api/**").authenticated()
      .anyRequest().permitAll()
      .and()
    .httpBasic().and()
    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}

1
Дякуємо за цей фрагмент коду, який може надати обмежену короткострокову допомогу. Правильне пояснення значно покращило б його довгострокове значення, показавши, чому це хороше рішення проблеми, і зробило б його більш корисним для майбутніх читачів з іншими подібними питаннями. Будь ласка, відредагуйте свою відповідь, щоб додати пояснення, включаючи припущення, які ви зробили.
Тобі Спейт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.