Spring Cloud 安全简介
一、概述
Spring Cloud Security 模块提供与 Spring Boot 应用程序中基于令牌的安全性相关的功能。
具体来说,它使基于 OAuth2 的 SSO 更容易——支持在资源服务器之间中继令牌,以及使用嵌入式 Zuul 代理配置下游身份验证。
在这篇快速文章中,我们将了解如何使用 Spring Boot 客户端应用程序、授权服务器和作为资源服务器的 REST API 来配置这些功能。
请注意,对于此示例,我们只有一个使用 SSO 来演示云安全功能的客户端应用程序 - 但在典型场景中,我们将至少有两个客户端应用程序来证明对单点登录的需求。
2. 快速启动云安全应用
让我们从在 Spring Boot 应用程序中配置 SSO 开始。
首先,我们需要添加spring-cloud-starter-oauth2依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
这也将引入spring-cloud-starter-security依赖项。
我们可以将任何社交网站配置为我们网站的身份验证服务器,也可以使用我们自己的服务器。在我们的例子中,我们选择了后一个选项并配置了一个充当授权服务器的应用程序——它在本地部署在http://localhost:7070/authserver。
我们的授权服务器使用 JWT 令牌。
此外,为了让任何客户端能够检索用户的凭据,我们需要配置在端口 9000 上运行的资源服务器,并使用可以提供这些凭据的端点。
在这里,我们配置了一个 / user端点,该端点位于http://localhost:9000/user。
有关如何设置授权服务器和资源服务器的更多详细信息,请在此处查看我们之前的文章。
我们现在可以在客户端应用程序的配置类中添加注释:
@Configuration
@EnableOAuth2Sso
public class SiteSecurityConfigurer
extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// ...
}
}
任何需要身份验证的请求都将被重定向到授权服务器。为此,我们还必须定义服务器属性:
security:
oauth2:
client:
accessTokenUri: http://localhost:7070/authserver/oauth/token
userAuthorizationUri: http://localhost:7070/authserver/oauth/authorize
clientId: authserver
clientSecret: passwordforauthserver
resource:
userInfoUri: http://localhost:9000/user
请注意,我们需要在类路径中包含spring-boot-starter-security才能找到上述配置。
3. 中继访问令牌
在中继令牌时,OAuth2 客户端将其收到的 OAuth2 令牌转发到传出资源请求。
由于我们已经声明了@EnableOauth2Sso注释,Spring Boot在请求范围内添加了一个OAuth2ClientContext bean。基于此,我们可以在客户端应用程序中创建自己的OAuth2RestTemplate:
@Bean
public OAuth2RestOperations restOperations(
OAuth2ProtectedResourceDetails resource, OAuth2ClientContext context) {
return new OAuth2RestTemplate(resource, context);
}
一旦我们配置了 bean ,上下文会将访问令牌转发给请求的服务,并且如果令牌过期,也会刷新令牌。
4. 使用RestTemplate中继 OAuth 令牌
我们之前在客户端应用程序中定义了一个OAuth2RestTemplate类型的restOperations bean。因此,我们可以使用 OAuth2RestTemplate 的getForObject ()方法将带有必要令牌的请求从我们的客户端发送到受保护的资源服务器。
首先,让我们在资源服务器中定义一个需要身份验证的端点:
@GetMapping("/person")
@PreAuthorize("hasAnyRole('ADMIN', 'USER')")
public @ResponseBody Person personInfo(){
return new Person("abir", "Dhaka", "Bangladesh", 29, "Male");
}
这是一个简单的 REST 端点,它返回一个Person对象的 JSON 表示。
现在,我们可以使用getForObject()方法从客户端应用程序发送请求,该方法会将令牌中继到资源服务器:
@Autowired
private RestOperations restOperations;
@GetMapping("/personInfo")
public ModelAndView person() {
ModelAndView mav = new ModelAndView("personinfo");
String personResourceUrl = "http://localhost:9000/person";
mav.addObject("person",
restOperations.getForObject(personResourceUrl, String.class));
return mav;
}
5.为令牌中继配置Zuul
如果我们想将令牌向下游中继到代理服务,我们可以使用 Spring Cloud Zuul Embedded Reverse Proxy。
首先,我们需要添加使用 Zuul 的 Maven 依赖项:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
接下来,我们需要在Client应用的配置类中添加@EnableZuulProxy注解:
@Configuration
@EnableOAuth2Sso
@EnableZuulProxy
public class SiteSecurityConfigurer
extends WebSecurityConfigurerAdapter {
//...
}
剩下要做的就是将 Zuul 配置属性添加到我们的application.yml文件中:
zuul:
sensitiveHeaders: Cookie,Set-Cookie
routes:
resource:
path: /api/**
url: http://localhost:9000
user:
path: /user/**
url: http://localhost:9000/user
任何到达客户端应用程序 / api端点的请求都将被重定向到资源服务器 URL。我们还需要提供用户凭据端点的 URL。
六,结论
在这篇快速文章中,我们探讨了如何将 Spring Cloud Security 与 OAuth2 和 Zuul 一起使用来配置安全授权和资源服务器,以及如何使用Oauth2RestTemplate和 Embedded Zuul Proxy 在服务器之间中继 OAuth2 令牌