英文:
OAuth2 with Asymmetric Approache
问题
我已经使用 Spring Cloud OAuth2 实现了一个资源服务器和授权服务器。当我使用默认方法实现 OAuth 应用程序(而不使用非对称或对称方法)时,授权服务器会生成默认令牌。当我需要与资源服务器和授权服务器通信时,可以在资源服务器配置文件中使用以下属性。
resource-server.yml 默认配置
security:
oauth2:
client:
client-id: web
client-secret: *****
resource:
token-info-uri: "http://localhost:9092/oauth/check_token"
当我在授权服务器中使用非对称方法使用私钥对令牌进行签名,并在资源服务器中使用公钥验证令牌时,使用以下属性 security:jwt:public-key: classpath:public.txt
调用资源服务器时出现以下未经授权的响应。
resource-server.yml 使用非对称方法配置
security:
jwt:
public-key: classpath:public.txt
API Endpoint
http://localhost:9090/user?Authorization=bearer **********
响应
{
"error": "invalid_token",
"error_description": "Cannot convert access token to JSON"
}
注意 - 当我在 resource-server.yml
中的非对称方法中使用 client
和 token-info-uri
属性时,会出现以下错误。
Method springSecurityFilterChain in org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration required a single bean, but 2 were found:
- tokenServices: defined by method 'tokenServices' in class path resource [com/benz/resource/api/config/ResourceServerConfiguration.class]
- remoteTokenServices: defined by method 'remoteTokenServices' in class path resource [org/springframework/boot/autoconfigure/security/oauth2/resource/ResourceServerTokenServicesConfiguration$RemoteTokenServicesConfiguration$TokenInfoServicesConfiguration.
我需要澄清以下问题:
-
在不使用
token-info-uri
和client
属性的情况下,资源服务器如何识别特定的授权服务器? -
为什么会发生未经授权的错误(如上所述)?
ResourceServerConfig 类
@Configuration
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Value("${security.jwt.public-key}")
private Resource publicKey;
private TokenStore tokenStore;
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.tokenStore(tokenStore());
}
@Bean
public DefaultTokenServices tokenServices(TokenStore tokenStore) {
DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setTokenStore(tokenStore);
return tokenServices;
}
@Bean
public TokenStore tokenStore() throws Exception {
if (tokenStore == null)
tokenStore = new JwtTokenStore(tokenConverter());
return tokenStore;
}
private JwtAccessTokenConverter tokenConverter() throws Exception {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setVerifierKey(getPublicKeyAsString());
return converter;
}
private String getPublicKeyAsString() throws Exception {
return IOUtils.toString(publicKey.getInputStream(), StandardCharsets.UTF_8);
}
}
GitHub 链接
resource-server-implementation
authorization-server-implementation
如果需要更多细节,请提出评论,我将进行更新。
英文:
I have implemented a resource server and authorization server with spring cloud oauth2. When I implemented the OAuth application by using the default approach (without using asymmetric or symmetric approach) then the default token is generated by the authorization server and when I have to communicate with the resource server and the authorization server then the following properties can be used in the resource server config file.
resource-server.yml with default
security:
oauth2:
client:
client-id: web
client-secret: *****
resource:
token-info-uri: "http://localhost:9092/oauth/check_token"
When I use an asymmetric approach to sign the token with the private key in the authorization server and use the public key to validate the token in the resource server with the following property security:jwt:public-key: classpath:public.txt
then the following unauthorized response has occurred when I call the resource from the resource server.
resource-server.yml with asymmetric
security:
jwt:
public-key: classpath:public.txt
API Endpoint
http://localhost:9090/user?Authorization=bearer **********
Response
{
"error": "invalid_token",
"error_description": "Cannot convert access token to JSON"
}
Note - when I use client
and token-info-uri
properties with an asymmetric approach in the resource-server.yml then the following error has occurred.
Method springSecurityFilterChain in org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration required a single bean, but 2 were found:
- tokenServices: defined by method 'tokenServices' in class path resource [com/benz/resource/api/config/ResourceServerConfiguration.class]
- remoteTokenServices: defined by method 'remoteTokenServices' in class path resource [org/springframework/boot/autoconfigure/security/oauth2/resource/ResourceServerTokenServicesConfiguration$RemoteTokenServicesConfiguration$TokenInfoServicesConfiguration.
I have to clarify the following question
-
Without using
token-info-uri
andclient
properties how does the resource server identify the particular authorization server?. -
why does the unauthorized error has occurred (which is mentioned in the above)?
ResourceServerConfig class
@Configuration
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Value("${security.jwt.public-key}")
private Resource publicKey;
private TokenStore tokenStore;
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.tokenStore(tokenStore());
}
@Bean
public DefaultTokenServices tokenServices(TokenStore tokenStore)
{
DefaultTokenServices tokenServices=new DefaultTokenServices();
tokenServices.setTokenStore(tokenStore);
return tokenServices;
}
@Bean
public TokenStore tokenStore() throws Exception
{
if(tokenStore==null)
tokenStore=new JwtTokenStore(tokenConverter());
return tokenStore;
}
private JwtAccessTokenConverter tokenConverter() throws Exception
{
JwtAccessTokenConverter converter=new JwtAccessTokenConverter();
converter.setVerifierKey(getPublicKeyAsString());
return converter;
}
private String getPublicKeyAsString() throws Exception
{
return IOUtils.toString(publicKey.getInputStream(),UTF_8);
}
}
Github link for
resource-server-implementation
authorization-server-implemetation
If you need more details please comment it then I can update
答案1
得分: 1
我已经解决了这个问题。在我的情况下,tokenConverter
方法是在创建 JwtTokenStore
bean 实例时被调用的。我已经改变了创建 JwtAccessTokenConverter
bean 实例的方法,通过添加 @Bean 注解来单独创建它。在这种情况下,它可以在没有任何中断的情况下正常工作。
@Bean
public JwtAccessTokenConverter tokenConverter() throws Exception
{
JwtAccessTokenConverter converter=new JwtAccessTokenConverter();
converter.setVerifierKey(getPublicKeyAsString());
return converter;
}
英文:
I have solved the issue. In my case, tokenConverter
method is called at the time of JwtTokenStore
bean instance created. I have changed the approach to create the bean instance for JwtAccessTokenConverter
separately by adding @Bean annotation. In that case, it is worked without any interruption.
@Bean
public JwtAccessTokenConverter tokenConverter() throws Exception
{
JwtAccessTokenConverter converter=new JwtAccessTokenConverter();
converter.setVerifierKey(getPublicKeyAsString());
return converter;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论