swagger 无法访问 OAuth2
Posted
技术标签:
【中文标题】swagger 无法访问 OAuth2【英文标题】:OAuth2 is not accessible from swagger 【发布时间】:2019-03-25 04:20:04 【问题描述】:当我尝试从 swagger 访问 OAuth2 时收到 401。如果 Swagger 在同一个项目中配置并在同一个端口上运行,它工作正常。但是当我在另一个具有不同端口的项目中配置 swagger 时,它会给出 401。
OAuth2 可以访问并且可以与 Postman 一起正常工作。我无法找到为什么它从不同的端口给出 401。我检查了正在运行的端口的入站/出站规则。从不同的服务器或端口访问 OAuth 是否需要任何其他配置?
OAuth2 项目配置在http://localhost:8090/ SpringBoot 项目在http://localhost:8888/ 上配置,OAuth2 提供 401。
网络安全配置
@Configuration
@EnableWebSecurity
public class CustomWebSecurityConfig extends WebSecurityConfigurerAdapter
@Lazy
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
public void configureGlobal(final AuthenticationManagerBuilder auth) throws Exception
auth
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder);
@Override
public void configure(HttpSecurity http) throws Exception
http
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS).permitAll()
.antMatchers("/oauth/**").permitAll()
.antMatchers("/login").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic()
.and()
.csrf().disable();
/*
* https://github.com/spring-projects/spring-boot/issues/11136
* Expose it manually (there is bug)
*
* */
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception
return super.authenticationManagerBean();
授权服务器配置:
@Configuration
@EnableAuthorizationServer
public class CustomAuthorizationServerConfig extends AuthorizationServerConfigurerAdapter
private static final String CLIENT_ID = "client";
private static final String CLIENT_SECRET = "secret";
private static final String GRANT_TYPE_PASSWORD = "password";
private static final String GRANT_TYPE_CLIENT_CREDENTIALS = "client_credentials";
private static final String GRANT_TYPE_REFRESH_TOKEN = "refresh_token";
private static final String GRANT_TYPE_AUTH_CODE = "authorization_code";
private static final String SCOPE_READ = "read";
private static final String SCOPE_WRITE = "write";
private static final String SCOPE_TRUST = "trust";
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private CustomUserDetailService userDetailsService;
@Autowired
private PasswordEncoder passwordEncoder;
@Value("$config.oauth2.tokenTimeout")
private int ACCESS_TOKEN_VALIDITY_SECONDS;
@Value("$config.oauth2.tokenTimeout")
private int REFRESH_TOKEN_VALIDITY_SECONDS;
@Value("$config.oauth2.privateKey")
private String privateKey;
@Value("$config.oauth2.publicKey")
private String publicKey;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception
clients
.inMemory()
.withClient(CLIENT_ID)
.authorizedGrantTypes(GRANT_TYPE_CLIENT_CREDENTIALS, GRANT_TYPE_PASSWORD, GRANT_TYPE_REFRESH_TOKEN, GRANT_TYPE_AUTH_CODE)
.authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
.scopes(SCOPE_READ, SCOPE_WRITE, SCOPE_TRUST)
.resourceIds("oauth2-resource")
.accessTokenValiditySeconds(ACCESS_TOKEN_VALIDITY_SECONDS)
.refreshTokenValiditySeconds(REFRESH_TOKEN_VALIDITY_SECONDS)
.secret(passwordEncoder.encode(CLIENT_SECRET));
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception
endpoints.authenticationManager(authenticationManager)
.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST)
.tokenStore(tokenStore())
.userDetailsService(userDetailsService)
.tokenServices(tokenServices())
.accessTokenConverter(accessTokenConverter());
@Bean
public JwtAccessTokenConverter accessTokenConverter()
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(privateKey);
return converter;
@Bean
public JwtTokenStore tokenStore()
return new JwtTokenStore(accessTokenConverter());
@Bean
@Primary
public DefaultTokenServices tokenServices()
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
defaultTokenServices.setSupportRefreshToken(true);
defaultTokenServices.setTokenEnhancer(accessTokenConverter());
return defaultTokenServices;
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception
security.checkTokenAccess("isAuthenticated()")
.tokenKeyAccess("permitAll()");
WebSecureConfigurerAdapter:
@Configuration
@EnableResourceServer
public class CustomResourceConfig extends ResourceServerConfigurerAdapter
@Value("$config.oauth2.publicKey")
private String publicKey;
@Value("$config.oauth2.privateKey")
private String privateKey;
@Value("$config.oauth2.resource.id")
private String resourceId;
@Override
public void configure(HttpSecurity http) throws Exception
http
.csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS).authenticated()
.antMatchers(HttpMethod.OPTIONS).permitAll()
.antMatchers("/", "/home", "/register", "/login").permitAll()
.antMatchers("/oauth/**").authenticated();
@Override
public void configure(ResourceServerSecurityConfigurer resources)
resources
.resourceId(resourceId)
.tokenServices(tokenServices())
.tokenStore(tokenStore());
@Bean
@Primary
public DefaultTokenServices tokenServices()
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
defaultTokenServices.setSupportRefreshToken(true);
defaultTokenServices.setTokenEnhancer(accessTokenConverter());
return defaultTokenServices;
@Bean
public JwtAccessTokenConverter accessTokenConverter()
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(privateKey);
return converter;
@Bean
public JwtTokenStore tokenStore()
return new JwtTokenStore(accessTokenConverter());
【问题讨论】:
也许项目需要一些 Cors 配置? 【参考方案1】:在 Swagger 配置中,应在创建 Docket 实例时正确初始化 OAuth 安全架构。这里的访问令牌 URI 类似于:http://localhost:8080/api/oauth/token
@Value("$config.oauth2.accessTokenUri")
private String accessTokenUri;
@Bean
public Docket productApi()
return new Docket(DocumentationType.SWAGGER_2)
.select().apis(RequestHandlerSelectors.basePackage("com.authentication")).paths(regex("/.*"))
.paths(PathSelectors.any())
.build()
.securityContexts(Collections.singletonList(securityContext()))
.securitySchemes(Arrays.asList(securitySchema()))
.apiInfo(apiInfo());
private OAuth securitySchema()
List<AuthorizationScope> authorizationScopeList = newArrayList();
authorizationScopeList.add(new AuthorizationScope("read", "read all"));
authorizationScopeList.add(new AuthorizationScope("write", "access all"));
List<GrantType> grantTypes = newArrayList();
GrantType passwordCredentialsGrant = new ResourceOwnerPasswordCredentialsGrant(accessTokenUri);
grantTypes.add(passwordCredentialsGrant);
return new OAuth("oauth2", authorizationScopeList, grantTypes);
private SecurityContext securityContext()
return SecurityContext.builder().securityReferences(defaultAuth())
.build();
【讨论】:
以上是关于swagger 无法访问 OAuth2的主要内容,如果未能解决你的问题,请参考以下文章
解决 Nginx 部署,无法访问 Swagger 文档的问题
解决 Nginx 部署,无法访问 Swagger 文档的问题
springboot 集成swagger2 404 无法访问
Spring Boot Security - 如果用户未通过 Oauth2 进行身份验证,如何禁用对 swagger ui 页面的端点的访问