Ric*_*ler 12 java spring oauth-2.0 jwt spring-security-oauth2
我正在尝试为spring项目配置OAuth2.我正在使用我的工作场所提供的共享UAA(来自云代工厂的oauth实现)实例(因此我不打算创建授权服务器,并且授权服务器与资源服务器分开).前端是单页面应用程序,它使用隐式授权直接从授权服务器获取令牌.我有SPA设置,它Authorization: Bearer <TOKEN>在每个Web API调用微服务时添加标题.
我现在的问题是微服务.
我正在尝试使用此共享授权服务器来验证微服务.我可能在这里有一个误解,购买我目前的理解是这些微服务扮演资源服务器的角色,因为它们托管SPA用来获取数据的端点.
所以我尝试配置像这样的微服务:
@Configuration
@EnableResourceServer
public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/api/**").authenticated();
}
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setVerifierKey("-----BEGIN PUBLIC KEY-----<key omitted>-----END PUBLIC KEY-----");
return converter;
}
@Bean
@Primary
public DefaultTokenServices tokenServices() {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
return defaultTokenServices;
}
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.tokenServices(tokenServices());
}
}
Run Code Online (Sandbox Code Playgroud)
现在每当我点击/api/**时Authorization: Bearer <TOKEN>,我得到一个403有这个错误:
{
"error": "access_denied",
"error_description": "Invalid token does not contain resource id (oauth2-resource)"
}
Run Code Online (Sandbox Code Playgroud)
Principal控制器方法?我目前已经设置了SPA所在的位置并发送令牌,我还有用于验证令牌签名的公钥.我还使用jwt.io测试令牌,并说"Signature Verified".谢谢!
tso*_*akp 25
Spring OAuth期望在JWT令牌中声明 "aud" .该声明的值应与resourceId您指定的Spring应用程序的值匹配(如果未指定,则默认为"oauth2-resource").
要解决您的问题,您需要:
1)登录您的共享UAA并确保它包含"aud"声明.
2)将"aud"声明的值更改为"oauth2-resource",或者最好在Spring应用更新中resourceId更改为该声明的值,如下所示:
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.tokenServices(tokenServices());
resources.resourceId(value from the aud claim you got from UAA server);
}
Run Code Online (Sandbox Code Playgroud)
小智 5
我添加了一个类似的问题。就我而言,我使用了 jdbc 身份验证,而我的授权服务器和资源服务器是两个独立的 API。
授权服务器
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
oauthServer.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()")
.passwordEncoder(oauthClientPasswordEncoder);
Run Code Online (Sandbox Code Playgroud)
}
/**
* Define the client details service. The client may be define either as in memory or in database.
* Here client with be fetch from the specify database
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.jdbc(dataSource);
}
/**
* Define the authorization by providing authentificationManager
* And the token enhancement
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints.tokenStore(tokenStore())
.tokenEnhancer(getTokenEnhancer())
.authenticationManager(authenticationManager).userDetailsService(userDetailsService);
}
Run Code Online (Sandbox Code Playgroud)资源服务器
public class OAuth2ResourceServerConfig extends
ResourceServerConfigurerAdapter {
private TokenExtractor tokenExtractor = new BearerTokenExtractor();
@Autowired
private DataSource dataSource;
@Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.addFilterAfter(new OncePerRequestFilter() {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
// We don't want to allow access to a resource with no token so clear
// the security context in case it is actually an OAuth2Authentication
if (tokenExtractor.extract(request) == null) {
SecurityContextHolder.clearContext();
}
filterChain.doFilter(request, response);
}
}, AbstractPreAuthenticatedProcessingFilter.class);
http.csrf().disable();
http.authorizeRequests().anyRequest().authenticated();
}
@Bean
public AccessTokenConverter accessTokenConverter() {
return new DefaultAccessTokenConverter();
}
@Bean
public RemoteTokenServices remoteTokenServices(final @Value("${auth.server.url}") String checkTokenUrl,
final @Value("${auth.resource.server.clientId}") String clientId,
final @Value("${auth.resource.server.clientsecret}") String clientSecret) {
final RemoteTokenServices remoteTokenServices = new RemoteTokenServices();
remoteTokenServices.setCheckTokenEndpointUrl(checkTokenUrl);
remoteTokenServices.setClientId(clientId);
remoteTokenServices.setClientSecret(clientSecret);
remoteTokenServices.setAccessTokenConverter(accessTokenConverter());
return remoteTokenServices;
}
Run Code Online (Sandbox Code Playgroud)有了这个配置,我得到了
{
"error": "access_denied",
"error_description": "Invalid token does not contain resource id
(xxxxx)"
}
Run Code Online (Sandbox Code Playgroud)
为了解决这个问题,我不得不添加
private String resourceIds= "xxxxx". !! maked sure that this resourceids is store in oauth_client_details for the clientid I used to get the token
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId(resourceIds).tokenStore(tokenStore());
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10544 次 |
| 最近记录: |