更多详细信息
单点登录
| 所有 OAuth2 SSO 和资源服务器功能已在 Spring Boot 1.3 版本中迁移至 Spring Boot。您可以在 Spring Boot 用户指南 中找到相关文档。 |
Token 中继
Tokens中继是指一个OAuth2消费者充当客户端,并将传入的Tokens转发到传出的资源请求。该消费者可以是纯客户端(如SSO应用程序)或资源服务器。
在 Spring Cloud Gateway 中使用客户端Tokens中继
如果您的应用程序还嵌入了 Spring Cloud Gateway 嵌入式反向代理,那么您可以要求它将OAuth2访问Tokens转发到下游服务。因此,上述SSO应用可以简单地通过这种方式进行增强:
@Autowired
private TokenRelayGatewayFilterFactory filterFactory;
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("resource", r -> r.path("/resource")
.filters(f -> f.filter(filterFactory.apply()))
.uri("http://localhost:9000"))
.build();
}
或者这个
spring:
cloud:
gateway:
routes:
- id: resource
uri: http://localhost:9000
predicates:
- Path=/resource
filters:
- TokenRelay=
并且它会(除记录用户登录并获取Tokens外)
将身份验证Tokens传递给下游服务(在这种情况下
/resource)。
要为 Spring Cloud Gateway 启用此功能,请添加以下依赖项
-
org.springframework.boot:spring-boot-starter-oauth2-client -
org.springframework.cloud:spring-cloud-starter-security
它是如何工作的?过滤器从当前认证的用户中提取访问Tokens,并将其放入请求头中,以便在下游请求中使用。
有关完整的工作示例,请参阅此项目。
ReactiveOAuth2AuthorizedClientService 的默认实现由 TokenRelayGatewayFilterFactory
使用内存中的数据存储。如果您需要更强大的解决方案,
则必须提供自己的实现 ReactiveOAuth2AuthorizedClientService。 |
客户端Tokens中继
如果您的应用程序是一个面向用户的 OAuth2 客户端(即已声明 @EnableOAuth2Sso 或 @EnableOAuth2Client),则它在请求作用域中将拥有一个 OAuth2ClientContext,由 Spring Boot 提供。您可以从此上下文中创建自己的 OAuth2RestTemplate,并结合一个自动注入的 OAuth2ProtectedResourceDetails,之后该上下文将始终将访问Tokens转发至下游服务,并在访问Tokens过期时自动刷新它。(这些功能属于 Spring Security 和 Spring Boot。)
Sprint Boot(1.4.1)在使用 client_credentials Tokens时不会自动创建一个 OAuth2ProtectedResourceDetails。 在这种情况下,您需要创建自己的 ClientCredentialsResourceDetails 并用 @ConfigurationProperties("security.oauth2.client") 进行配置。 |
在Zuul代理中进行客户端Tokens传递
如果您的应用程序还具有嵌入式反向代理(使用@EnableZuulProxy)的Spring Cloud Zuul,则可以要求它将OAuth2访问Tokens转发到下游服务。因此,上述SSO应用可以通过以下方式简单增强:
@Controller
@EnableOAuth2Sso
@EnableZuulProxy
class Application {
}
此外,它还会将身份验证Tokens传递给下游的 /proxy/* 服务。如果这些服务是使用 @EnableResourceServer 实现的,那么它们将在正确的标头中获得有效的Tokens。
它是如何工作的?@EnableOAuth2Sso 注解会导入spring-cloud-starter-security(您可以在传统应用程序中手动完成),这又触发了对ZuulFilter 的一些自动配置,而它本身因为Zuul在类路径上(通过@EnableZuulProxy)被激活。该过滤器仅从当前已认证用户提取访问Tokens,并将其放入下游请求的请求头中。
Sprint Boot 不会自动生成所需的 OAuth2RestOperations,因此在这种情况下,您需要创建自己的 OAuth2RestOperations,以便在需要时让 OAuth2TokenRelayFilter 刷新Tokens。 |
资源服务器Tokens中继
如果您的应用程序具有 @EnableResourceServer,您可能希望将传入的Tokens下游传递给其他服务。如果您使用 RestTemplate 与下游服务进行通信,则只需如何创建带有正确上下文的模板即可。
如果您的服务使用UserInfoTokenServices来验证传入的Tokens(即它正在使用security.oauth2.user-info-uri配置),那么您可以简单地创建一个OAuth2RestTemplate,并使用自动装配的OAuth2ClientContext(在到达后端代码之前,会由认证过程填充)。等效地(使用Spring Boot 1.4),您可以注入一个UserInfoRestTemplateFactory并在配置中获取其OAuth2RestTemplate。例如:
@Bean
public OAuth2RestTemplate restTemplate(UserInfoRestTemplateFactory factory) {
return factory.getUserInfoRestTemplate();
}
此 REST 模板将具有与身份验证过滤器相同的 OAuth2ClientContext(请求作用域),因此您可以使用它以相同的访问Tokens发送请求。
如果您的应用程序未使用 UserInfoTokenServices,但仍是一个客户端(即声明了 @EnableOAuth2Client 或 @EnableOAuth2Sso),那么在 Spring Security Cloud 中,用户从一个 @Autowired OAuth2Context 创建任何 OAuth2RestOperations 时也会转发Tokens。此功能默认通过 MVC 处理程序拦截器实现,因此仅适用于 Spring MVC。如果不使用 MVC,可以使用自定义过滤器或包装 AccessTokenContextRelay 的 AOP 拦截器来提供相同的功能。
以下是一个基本示例,展示了如何使用在其他地方创建的自动注入的 REST 模板(“foo.com” 是一个资源服务器,接受与周围应用程序相同的Tokens):
@Autowired
private OAuth2RestOperations restTemplate;
@RequestMapping("/relay")
public String relay() {
ResponseEntity<String> response =
restTemplate.getForEntity("https://foo.com/bar", String.class);
return "Success! (" + response.getBody() + ")";
}
如果您不想转发Tokens(这当然是一种合理的选择,因为您可能希望以自身身份行事,而非代表发送Tokens的客户端),那么您只需创建自己的 OAuth2Context,而无需自动装配默认的那一个。
Feign 客户端也会拾取一个拦截器,该拦截器在可用时使用 OAuth2ClientContext,因此它们也应在任何需要进行 RestTemplate Tokens中继的地方执行Tokens中继。