Springfox 2.5.0を使用してAPIで「Authorization:Bearer __」が送信されない理由を理解できません。次の構成があります。
private ApiKey apiKey() {
return new ApiKey(
"Authorization", // name: My key - Authorization
"api_key", // keyname: api_key
"header");
}
@Bean
SecurityConfiguration security() {
return new SecurityConfiguration(
null, null, null,
"Docserver2_fwk", // app name
"BEARER", // api key value
ApiKeyVehicle.HEADER, "Authorization", ",");
}
Springfox(2.5.0)で「Authorization:Bearer Token」を送信できないようですが、これは可能ですか?それは既知の問題ですか?
同様の問題: https://github.com/springfox/springfox/issues/1812
PS:OpenAPI 3.0では、「bearer」形式を使用できます。例: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#jwt-bearer-sample =
ありがとう。
_2.8.0
_バージョンを使用しており、以下のswagger設定が動作します。私はコメントで言及しましたが、バージョン_2.7.0
_ではすべてがうまく機能していましたが、_2.8.0
_にアップグレードし、jwtトークンはリクエストヘッダーで送信されなくなりましたSpring Bootバージョン-_1.5.2.RELEASE
_を使用しています。
JWTトークンをユーザーが手動で入力できるUIが必要なことに注意してください-ベアラー...そしてトークンはAuthorization
リクエストヘッダーに入れる必要がありますOAuthサーバーと自動的に統合されません。
_import Java.time.LocalDate;
import Java.util.Arrays;
import Java.util.List;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.ResponseEntity;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger.web.SecurityConfiguration;
import springfox.documentation.swagger.web.SecurityConfigurationBuilder;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import com.google.common.base.Predicates;
import com.google.common.collect.Lists;
@Configuration
@EnableSwagger2
public class SwaggerConfig extends WebMvcConfigurerAdapter {
@SuppressWarnings("unchecked")
@Bean
public Docket swaggerPlugin() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.paths(PathSelectors.any())
.apis(Predicates.or(RequestHandlerSelectors
.basePackage("**controller package 1**"),
RequestHandlerSelectors
.basePackage("**controller package 2**")))
.build().directModelSubstitute(LocalDate.class, String.class)
.genericModelSubstitutes(ResponseEntity.class)
.apiInfo(apiInfo())
.securitySchemes(Lists.newArrayList(apiKey()))
.securityContexts(Arrays.asList(securityContext()));
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder().title("**Comment**")
.description("**Comment**")
.termsOfServiceUrl("**Comment**")
.contact("**Comment**")
.license("Apache License Version 2.0")
.licenseUrl("**Comment**").version("0.0.1")
.build();
}
@Bean
public SecurityConfiguration security() {
return SecurityConfigurationBuilder.builder().scopeSeparator(",")
.additionalQueryStringParams(null)
.useBasicAuthenticationWithAccessCodeGrant(false).build();
}
@Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html").addResourceLocations(
"classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations(
"classpath:/META-INF/resources/webjars/");
}
private ApiKey apiKey() {
return new ApiKey("apiKey", "Authorization", "header");
}
private SecurityContext securityContext() {
return SecurityContext.builder().securityReferences(defaultAuth())
.forPaths(PathSelectors.any()).build();
}
private List<SecurityReference> defaultAuth() {
AuthorizationScope authorizationScope = new AuthorizationScope(
"global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
return Arrays.asList(new SecurityReference("apiKey",
authorizationScopes));
}
}
_
リファレンス- このgithubの問題の回答はJotaroJewstarによる
簡単な回避策は、Bearer
と入力してからトークンを貼り付けることです。次を含むテキストボックスが表示されます。
Bearer <token>
もっと自動化された方法があればいいのに。しかし、今のところ、テキストボックスの単純な内容は、特定のヘッダーエントリの値セクションに貼り付けられているように見えます。接頭辞Bearer
が自動的に挿入されない理由は、Swaggerがユーザーが使用した認証の種類についてかなりの意見を持っているからだと思います!
@Configuration
@EnableSwagger2
class SwaggerConfig {
@Bean
Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(Predicates.not(PathSelectors.regex("/error.*")))
.build()
.securitySchemes(securitySchemes())
}
private static ArrayList<? extends SecurityScheme> securitySchemes() {
return [new ApiKey("Bearer", "Authorization", "header")]
}
}
RESTエンドポイントメソッド:
@GetMapping("/count")
@ApiOperation(value = "Count the number of entities associated with resource name. This operation does not requires any role." , authorizations = [@Authorization(value = "Bearer")])
def count() {
count(service)
}
ログインする前のcurl
コマンド:
curl -X GET "http://localhost:8080/category/count" -H "accept: */*"
応答:
{
"timestamp": "2018-10-29T15:13:02.388+0000",
"status": 401,
"error": "Unauthorized",
"message": "Unauthorized",
"path": "/category/count"
}
ログイン後のcurl
コマンド:
curl -X GET "http://localhost:8080/category/count" -H "accept: */*" -H "Authorization: Bearer eyJhbGciOiJIUzUxMiJ9..."
応答:
{
"message": "There are 0 entities",
"count": 0
}
注:私のコードはGroovyにあります。標準Javaを使用している場合は翻訳できると確信しています。
Swaggerversión2.9.2を使用して解決したソリューションは次のとおりです。
package com.example.springsocial;
import Java.util.Arrays;
import Java.util.Collections;
import Java.util.List;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import com.google.common.base.Predicates;
import com.google.common.collect.Lists;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class SwaggerConfiguration {
@Bean
public Docket docket() {
return new Docket(DocumentationType.SWAGGER_2)
.ignoredParameterTypes(AuthenticationPrincipal.class)
.select()
.apis(Predicates.not(RequestHandlerSelectors.basePackage("org.springframework.boot")))
.paths(PathSelectors.any()).build()
.securitySchemes(Lists.newArrayList(apiKey()))
.securityContexts(Arrays.asList(securityContext()));
}
private ApiKey apiKey() {
return new ApiKey("apiKey", "Authorization", "header");
}
private SecurityContext securityContext() {
return SecurityContext.builder().securityReferences(defaultAuth())
.forPaths(PathSelectors.any()).build();
}
private List<SecurityReference> defaultAuth() {
AuthorizationScope authorizationScope = new AuthorizationScope(
"global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
return Arrays.asList(new SecurityReference("apiKey",
authorizationScopes));
}
}
POM.XML
<!-- SWAGGER -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-bean-validators</artifactId>
<version>2.9.2</version>
</dependency>
SecurityConfig.Java
package com.example.springsocial.config;
import com.example.springsocial.security.*;
import com.example.springsocial.security.oauth2.CustomOAuth2UserService;
import com.example.springsocial.security.oauth2.HttpCookieOAuth2AuthorizationRequestRepository;
import com.example.springsocial.security.oauth2.OAuth2AuthenticationFailureHandler;
import com.example.springsocial.security.oauth2.OAuth2AuthenticationSuccessHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
securedEnabled = true,
jsr250Enabled = true,
prePostEnabled = true
)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomUserDetailsService customUserDetailsService;
@Autowired
private CustomOAuth2UserService customOAuth2UserService;
@Autowired
private OAuth2AuthenticationSuccessHandler oAuth2AuthenticationSuccessHandler;
@Autowired
private OAuth2AuthenticationFailureHandler oAuth2AuthenticationFailureHandler;
@Autowired
private HttpCookieOAuth2AuthorizationRequestRepository httpCookieOAuth2AuthorizationRequestRepository;
@Bean
public TokenAuthenticationFilter tokenAuthenticationFilter() {
return new TokenAuthenticationFilter();
}
/*
By default, Spring OAuth2 uses HttpSessionOAuth2AuthorizationRequestRepository to save
the authorization request. But, since our service is stateless, we can't save it in
the session. We'll save the request in a Base64 encoded cookie instead.
*/
@Bean
public HttpCookieOAuth2AuthorizationRequestRepository cookieAuthorizationRequestRepository() {
return new HttpCookieOAuth2AuthorizationRequestRepository();
}
@Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder
.userDetailsService(customUserDetailsService)
.passwordEncoder(passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean(BeanIds.AUTHENTICATION_MANAGER)
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.csrf()
.disable()
.formLogin()
.disable()
.httpBasic()
.disable()
.exceptionHandling()
.authenticationEntryPoint(new RestAuthenticationEntryPoint())
.and()
.authorizeRequests()
.antMatchers("/",
"/error",
"/favicon.ico",
"/**/*.png",
"/**/*.gif",
"/**/*.svg",
"/**/*.jpg",
"/**/*.html",
"/**/*.css",
"/**/*.js",
// swagger
"/swagger-ui.html**", "/swagger-resources/**",
"/v2/api-docs**", "/webjars/**"
)
.permitAll()
.antMatchers("/auth/**", "/oauth2/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.oauth2Login()
.authorizationEndpoint()
.baseUri("/oauth2/authorize")
.authorizationRequestRepository(cookieAuthorizationRequestRepository())
.and()
.redirectionEndpoint()
.baseUri("/oauth2/callback/*")
.and()
.userInfoEndpoint()
.userService(customOAuth2UserService)
.and()
.successHandler(oAuth2AuthenticationSuccessHandler)
.failureHandler(oAuth2AuthenticationFailureHandler);
// Add our custom Token based authentication filter
http.addFilterBefore(tokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/common/**", "/v2/api-docs", "/configuration/ui", "/swagger-resources",
"/configuration/security", "/swagger-ui.html", "/webjars/**");
}
}
以下の構成でspringfox-swagger2バージョン-2.9.2を使用しましたが、swagger-ui経由でJWTトークンを渡すと正常に動作します。
private ApiKey apiKey() {
return new ApiKey("apiKey", Authorization, "header");
}
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2).select()
.apis(RequestHandlerSelectors.basePackage("com.mycompany.dept.controller"))
.paths(PathSelectors.any())
.build().apiInfo(metaData()).securitySchemes(Lists.newArrayList(apiKey()));
}
また、コントローラーでは@ApiOperationを使用する必要があります(値=「IDでダミーを取得」、authorizations = {@Authorization(value = "apiKey")})
https://github.com/springfox/springfox/issues/2194 を参照してください
以下のソリューションは、Swagger _2.8.0
_バージョンで機能しました。
Docket設定に以下のコードを追加します
_@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.securitySchemes(Collections.singletonList(new ApiKey("JWT", "Authorization", "header")))
.securityContexts(Collections.singletonList(
SecurityContext.builder()
.securityReferences(
Collections.singletonList(SecurityReference.builder()
.reference("JWT")
.scopes(new AuthorizationScope[0])
.build()
)
)
.build())
)
.select()
.apis(RequestHandlerSelectors
.basePackage("com.test.controller"))
.paths(PathSelectors.regex("/.*"))
.build().apiInfo(apiEndPointsInfo());
}
_
Swagger UIでAuthorize
ボタンをクリックした後のテキストボックスに、Bearer "XXXXXXXX(Token)"
と入力します