更多详情
单点登录
注意 | 所有OAuth2 SSO和资源服务器功能在版本1.3中移动到Spring Boot。您可以在Spring Boot用户指南中找到文档 。 |
令牌中继
令牌中继是OAuth2消费者充当客户端,并将传入令牌转发到外发资源请求。消费者可以是纯客户端(如SSO应用程序)或资源服务器。
客户端令牌中继
如果您的应用是面向OAuth2客户端的用户(即声明为@EnableOAuth2Sso
或@EnableOAuth2Client
),那么它的请求范围为spring security的OAuth2ClientContext
。您可以从此上下文和自动连线OAuth2ProtectedResourceDetails
创建自己的OAuth2RestTemplate
,然后上下文将始终向下转发访问令牌,如果过期则自动刷新访问令牌。(这些是Spring安全和Spring Boot的功能。)
注意 | 如果您使用client_credentials 令牌,则Spring Boot(1.4.1)不会自动创建OAuth2ProtectedResourceDetails 。在这种情况下,您需要创建自己的ClientCredentialsResourceDetails 并使用@ConfigurationProperties("security.oauth2.client") 进行配置。 |
客户端令牌中继在Zuul代理
如果您的应用程式还有 Spring Cloud Zuul嵌入式反向代理(使用@EnableZuulProxy
),那么您可以要求将OAuth2访问令牌转发到其正在代理的服务。因此,上述的SSO应用程序可以简单地增强:
@Controller
@EnableOAuth2Sso
@EnableZuulProxy
class Application {
}
并且(除了将用户登录并抓取令牌之外)将下载的身份验证令牌传递到/proxy/*
服务。如果这些服务是用@EnableResourceServer
实现的,那么他们将在正确的标题中获得一个有效的标记。
它是如何工作的?@EnableOAuth2Sso
注释引入spring-cloud-starter-security
(您可以在传统应用程序中手动执行),而这又会触发一个ZuulFilter
的自动配置,该属性本身被激活,因为Zuul在classpath(通过@EnableZuulProxy
)。该 过滤器 仅从当前已认证的用户提取访问令牌,并将其放入下游请求的请求头中。
资源服务器令牌中继
如果您的应用有@EnableResourceServer
,您可能希望将传入令牌下载到其他服务。如果您使用RestTemplate
联系下游服务,那么这只是如何使用正确的上下文创建模板的问题。
如果您的服务使用UserInfoTokenServices
验证传入令牌(即正在使用security.oauth2.user-info-uri
配置)),则可以使用自动连线OAuth2ClientContext
创建OAuth2RestTemplate
(将由身份验证过程之前它遇到后端代码)。相等(使用Spring Boot 1.4),您可以在配置中注入UserInfoRestTemplateFactory
并抓取其中的OAuth2RestTemplate
。例如:
@Bean
public OAuth2RestTemplate restTemplate(UserInfoRestTemplateFactory factory) {
return factory.getUserInfoRestTemplate();
}
然后,此休息模板将具有由身份验证过滤器使用的OAuth2ClientContext
(请求作用域)相同,因此您可以使用它来发送具有相同访问令牌的请求。
如果您的应用没有使用UserInfoTokenServices
,但仍然是客户端(即声明@EnableOAuth2Client
或@EnableOAuth2Sso
),则使用Spring安全云任何OAuth2RestOperations
,用户从@Autowired
@OAuth2Context
也会转发令牌。此功能默认实现为MVC处理程序拦截器,因此它仅适用于Spring MVC。如果您不使用MVC,可以使用包含AccessTokenContextRelay
的自定义过滤器或AOP拦截器来提供相同的功能。
以下是一个基本示例,显示了使用其他地方创建的自动连线休息模板(“foo.com”是一个资源服务器,接受与周围应用程序相同的令牌):
MyController.java@Autowired
private OAuth2RestOperations restTemplate;
@RequestMapping("/relay")
public String relay() {
ResponseEntity<String> response =
restTemplate.getForEntity("https://foo.com/bar", String.class);
return "Success! (" + response.getBody() + ")";
}
如果您不想转发令牌(这是一个有效的选择,因为您可能希望以自己的身份而不是向您发送令牌的客户端),那么您只需要创建自己的OAuth2Context
的自动装配默认值。
Feign客户端也会选择使用OAuth2ClientContext
的拦截器,如果它是可用的,那么他们还应该在RestTemplate
将要执行的令牌中继。