更多详情

优质
小牛编辑
147浏览
2023-12-01

单点登录

注意所有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应用程序可以简单地增强:

app.groovy
@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。例如:

MyConfiguration.java
@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将要执行的令牌中继。