简体   繁体   English

微服务和Spring Security OAuth2

[英]Microservices and Spring Security OAuth2

I already have a OAuth2 authorization server running in another project. 我已经在另一个项目中运行了OAuth2授权服务器。 Now I would need to secure several simple spring-boot rest-servers with OAuth2. 现在我需要使用OAuth2来保护几个简单的spring-boot rest-servers。 But I'm finding the Spring documentation really really limited when it comes to separating Authorization and Resource servers. 但是我发现Spring文档在分离授权和资源服务器时确实非常有限。

I've also found several questions where the answer has been "Well they can be different boxes as long as they share the same tokenStore datasource". 我还发现了几个问题, 答案是“只要它们共享相同的tokenStore数据源,它们就可以是不同的盒子”。 Can this really be true? 这真的可以吗? How could this ever work for microservices? 这怎么可能对微服务有用? It would seem like a really odd thing that every rest service would need to implement it's own OAuth authorization server. 每个休息服务都需要实现它自己的OAuth授权服务器,这似乎是一件非常奇怪的事情。

So how do I setup Oauth2.0 security for spring-boot rest-endpoints that refer to a remote oauth authorization server (possibly not even written with Spring)? 那么如何为引用远程oauth授权服务器的spring-boot rest-endpoints设置Oauth2.0安全性(可能甚至不用Spring编写)?

There's this thing called RemoteTokenServices that seems promising but it's not really documented at all. 这个名为RemoteTokenServices的东西似乎很有希望,但根本没有记录。

While configuring your auh server:: 配置你的auh服务器::

Create a new clientDetails in ClientDetailsServiceConfigurer for resource server. ClientDetailsServiceConfigurer为资源服务器创建新的clientDetails。 which will be used to configure RemoteTokenService . 这将用于配置RemoteTokenService

Configure Spring Security OAuth2 in your resource server: 在资源服务器中配置Spring Security OAuth2:

Create a class which is annotate with @EnableWebSecurity , @Configuration and extends WebSecurityConfigurerAdapter . 创建一个使用@EnableWebSecurity@Configuration @EnableWebSecurity @Configuration注释的类,并扩展WebSecurityConfigurerAdapter

@Configuration
@EnableWebSecurity
protected static class ResourceConfiguration extends WebSecurityConfigurerAdapter {
  // methods        
}

Create a method with @Bean annotated which will return instance of TokenService , which will be used to create AuthenticationManager . 使用@Bean注释创建一个方法,该方法将返回TokenService实例,该实例将用于创建AuthenticationManager

In this method create an instance of RemoteTokenService and set clientId, client_secret , checkTokenEndpointUrl and DefaultAccessTokenConverterWithClientRoles (this class is our implementation to get client_authority while authenticating accessToken in OAuth2 server.) 在此方法中创建RemoteTokenService的实例并设置clientId,client_secret,checkTokenEndpointUrl和DefaultAccessTokenConverterWithClientRoles (此类是我们在OAuth2服务器中验证accessToken时获取client_authority的实现。)

@Bean
public ResourceServerTokenServices tokenService() {
    RemoteTokenServices tokenServices = new RemoteTokenServices();
    tokenServices.setClientId("resource_id");
    tokenServices.setClientSecret("resource_secret");
    tokenServices.setCheckTokenEndpointUrl("http://<server-url>: <port>/oauth/check_token");
    return tokenServices;
}

Override authenticationManagerBean() method and annotate it with @Bean and return an instance of OAuth2AuthenticationManager with TokenService injected. 覆盖authenticationManagerBean()方法并使用@Bean注释它,并返回注入了OAuth2AuthenticationManagerTokenService实例。

@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
    OAuth2AuthenticationManager authenticationManager = new OAuth2AuthenticationManager();
    authenticationManager.setTokenServices(tokenService());
    return authenticationManager;
}

Create a class annotated with @EnableResourceServer , @Configuration and extend ResourceServerConfigurerAdapter . 创建一个使用@EnableResourceServer@Configuration @EnableResourceServer @Configuration注释的类并扩展ResourceServerConfigurerAdapter

@Configuration
@EnableResourceServer
protected static class ResourceServerConfig extends ResourceServerConfigurerAdapter {
  // Mehotds
}

Override Configure methods form the super class to configure resource server. 覆盖配置方法构成超类以配置资源服务器。 Different configurer to configure Resource server. 不同的配置器配置资源服务器。

ResourceServerSecurityConfigurer : to configure Resource_id. ResourceServerSecurityConfigurer :配置Resource_id。

HttpSecurity : This will configure security filter to tell it that user requires authentication for protected URLs (APIs). HttpSecurity :这将配置安全过滤器,告诉用户需要对受保护的URL(API)进行身份验证。

@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
    resources.resourceId("resource_id");
}

@Override
public void configure(HttpSecurity http) throws Exception {
    // @formatter:off
    http
     .authorizeRequests()
     .antMatchers("/**").authenticated()
     .and()
     .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    // @formatter:on
}

.antMatcher("/**").authenticated() this line will secure every api url of your resource server. .antMatcher("/**").authenticated()这一行将保护资源服务器的每个api url。 .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) will not create session. .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)不会创建会话。

PS:: If any thing is wrong then tell me. PS ::如果有什么不对的话请告诉我。

It's not really true that both have to share the same database, provided the resource server has some way of validating that the access token is genuine (was issued by the authorizations server) and also some way of decoding it (it may need to know what scopes it grants, for example). 如果资源服务器有某种方式来验证访问令牌是真实的(由授权服务器发布)以及解码它的某种方式(它可能需要知道什么,那么两者都必须共享同一个数据库并不是真的。例如,它授予的范围。 The OAuth2 spec doesn't say anything about how this is to be achieved. OAuth2规范没有说明如何实现这一目标。

If the resource is in the same process as the authorization server, then sharing the data is an easy option. 如果资源与授权服务器处于同一进程中,则共享数据是一个简单的选择。 Otherwise, it needs some way of translating the token. 否则,它需要某种方式来翻译令牌。 If the token is just an opaque string of random bytes, then obviously it has to exchange it for the real information. 如果令牌只是一个随机字节的不透明字符串,那么显然它必须将它交换为真实信息。 This is what RemoteTokenServices does. 这就是RemoteTokenServices功能。 The authorization server exposes a /check_token endpoint to allow the tokens to be decoded. 授权服务器公开/check_token端点以允许解码令牌。

An alternative is to actually encode the info in the token and have the authorization server digitally sign it. 另一种方法是实际编码令牌中的信息,并让授权服务器对其进行数字签名。 The resource server can then decode and validate the token itself as long as it understand the format. 然后资源服务器可以解码并验证令牌本身,只要它理解格式即可。

I'd recommend you look at the Cloudfoundry UAA which provides an authorization server out of the box which is implemented using signed JWT tokens (it also exposes the /check_token endpoint). 我建议您查看Cloudfoundry UAA ,它提供了一个开箱即用的授权服务器,它使用签名的JWT令牌实现(它还公开了/check_token端点)。 The Tokens overview and the API docs are probably a good starting point. 令牌概述API文档可能是一个很好的起点。

A working sample of RemoteTokenService can be found here . 可以在此处找到RemoteTokenService的工作示例。

For more details about check_token api, you can refer org.springframework.security.oauth2.provider.endpoint.CheckTokenEndpoint.java 有关check_token api的更多详细信息,请参阅org.springframework.security.oauth2.provider.endpoint.CheckTokenEndpoint.java

On the resource server end, OAuth2AuthenticationProcessingFilter validates OAuth2 token by calling OAuth2AuthenticationManager.authenticate() method which makes the call to RemoteTokenServices.loadAuthentication() to validate the token from the Auth Server. 在资源服务器端, OAuth2AuthenticationProcessingFilter通过调用OAuth2AuthenticationManager.authenticate()方法验证OAuth2令牌,该方法调用RemoteTokenServices.loadAuthentication()以验证来自Auth服务器的令牌。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM