Spring Cloud Security

Spring Cloud Security

Spring Cloud Security提供了一组用于构建安全应用程序和服务的原语,最小化。可以从外部(或集中)高度配置的声明式模型适用于通常使用中央契约管理服务的大型合作远程组件系统的实现。在像Cloud Foundry这样的服务平台上也很容易使用。基于Spring Boot和Spring安全性OAuth2,我们可以快速创建实现常见模式的系统,如单点登录,令牌中继和令牌交换。

注意 Spring Cloud根据非限制性Apache 2.0许可证发布。如果您想为文档的这一部分做出贡献,或者发现错误,请在github中找到项目中的源代码和问题跟踪器。

快速开始

OAuth2单一登录

这是一个具有HTTP基本身份验证和单个用户帐户的Spring Cloud“Hello World”应用程序

app.groovy

@Grab('spring-boot-starter-security')
@Controller
class Application {

  @RequestMapping('/')
  String home() {
    'Hello World'
  }

}

您可以使用spring run app.groovy运行它,并观察日志的密码(用户名为“用户”)。到目前为止,这只是一个Spring Boot应用程序的默认设置。

这是一个使用OAuth2 SSO的Spring Cloud应用程序:

app.groovy

@Controller
@EnableOAuth2Sso
class Application {

  @RequestMapping('/')
  String home() {
    'Hello World'
  }

}

指出不同?这个应用程序的行为实际上与之前的一样,因为它不知道它是OAuth2的信誉。

您可以很容易地在github注册一个应用程序,所以如果你想要一个生产应用程序在你自己的域上尝试。如果您很乐意在localhost:8080上测试,那么请在应用程序配置中设置这些属性:

application.yml

security:
  oauth2:
    client:
      clientId: bd1c0a783ccdd1c9b9e4
      clientSecret: 1a9030fbca47a5b2c28e92f19050bb77824b5ad1
      accessTokenUri: https://github.com/login/oauth/access_token
      userAuthorizationUri: https://github.com/login/oauth/authorize
      clientAuthenticationScheme: form
    resource:
      userInfoUri: https://api.github.com/user
      preferTokenInfo: false

运行上面的应用程序,它将重定向到github进行授权。如果您已经登录github,您甚至不会注意到它已经通过身份验证。只有您的应用程序在8080端口上运行,这些凭据才会起作用。

要限制客户端在获取访问令牌时要求的范围,您可以设置security.oauth2.client.scope(逗号分隔或YAML中的数组)。默认情况下,作用域为空,由授权服务器确定默认值是什么,通常取决于客户端注册中的设置。

注意 上面的例子都是Groovy脚本。如果要在Java(或Groovy)中编写相同的代码,则需要将Spring Security OAuth2添加到类路径中(例如,请参阅此处示例)。

OAuth2受保护资源

您要使用OAuth2令牌保护API资源?这是一个简单的例子(与上面的客户端配对):

app.groovy

@Grab('spring-cloud-starter-security')
@RestController
@EnableResourceServer
class Application {

  @RequestMapping('/')
  def home() {
    [message: 'Hello World']
  }

}

application.yml

security:
  oauth2:
    resource:
      userInfoUri: https://api.github.com/user
      preferTokenInfo: false

更多详情

单点登录

注意 所有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将要执行的令牌中继。

配置Zuul代理下游的认证

您可以通过proxy.auth.*设置控制@EnableZuulProxy下游的授权行为。例:

application.yml

proxy:
  auth:
    routes:
      customers: oauth2
      stores: passthru
      recommendations: none

在此示例中,“客户”服务获取OAuth2令牌中继,“存储”服务获取传递(授权头只是通过下游),“建议”服务已删除其授权头。如果有令牌可用,则默认行为是执行令牌中继,否则为passthru。

有关详细信息,请参阅ProxyAuthenticationProperties

欢迎关注作者的公众号《Java编程生活》,每日记载Java程序猿工作中遇到的问题
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_26648623/article/details/83311032