An Intro to Spring Cloud Security – Spring云安全介绍

最后修改: 2018年 2月 20日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

The Spring Cloud Security module provides features related to token-based security in Spring Boot applications.

Spring Cloud Security模块提供了与Spring Boot应用程序中基于令牌的安全有关的功能。

Specifically, it makes OAuth2-based SSO easier – with support for relaying tokens between Resource Servers, as well as configuring downstream authentication using an embedded Zuul proxy.

具体来说,它使基于OAuth2的SSO更容易–支持在资源服务器之间转发令牌,以及使用嵌入式Zuul代理配置下游认证。

In this quick article, we’ll have a look at how we can configure these features using a Spring Boot client application, an Authorization Server and a REST API working as a Resource Server.

在这篇文章中,我们将看看如何使用Spring Boot客户端应用程序、授权服务器和作为资源服务器的REST API来配置这些功能。

Note that for this example, we only have one Client application that uses SSO to demonstrate the cloud security features – but in a typical scenario, we would have at least two client applications to justify the need for Single Sign-On.

请注意,在这个例子中,我们只有一个客户端应用程序使用SSO来展示云安全功能 – 但在一个典型的场景中,我们至少有两个客户端应用程序来证明单点登录的必要性。

2. Quick Start a Cloud Security App

2.快速启动云安全应用程序

Let’s start by configuring SSO in a Spring Boot application.

让我们从在Spring Boot应用程序中配置SSO开始。

First, we need to add the spring-cloud-starter-oauth2 dependency:

首先,我们需要添加spring-cloud-starter-oauth2依赖性。

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-oauth2</artifactId>
    <version>2.2.2.RELEASE</version>
</dependency>

This will also bring in the spring-cloud-starter-security dependency.

这也将带来spring-cloud-starter-security的依赖。

We can configure any social site as an Auth Server for our site or we can use our own server. In our case, we’ve chosen the latter option and configured an application that acts as an Authorization Server – which is deployed locally at http://localhost:7070/authserver.

我们可以将任何社交网站配置为我们网站的授权服务器,或者我们可以使用我们自己的服务器。在我们的案例中,我们选择了后者,并配置了一个充当授权服务器的应用程序–它被部署在本地的http://localhost:7070/authserver.

Our authorization server uses JWT tokens.

我们的授权服务器使用JWT令牌。

Additionally, for any Client to be able to retrieve the credentials of a user, we need to configure our Resource Server, running on port 9000, with an endpoint which can serve these credentials.

此外,为了使任何客户端能够检索到用户的证书,我们需要配置我们的资源服务器,运行在9000端口上,有一个可以提供这些证书的端点。

Here, we’ve configured a /user endpoint that is available at http://localhost:9000/user.

在这里,我们配置了一个/user端点,该端点可在http://localhost:9000/user.

For more details on how to set up an Authorization Server and a Resource Server, check out our previous article here.

有关如何设置授权服务器和资源服务器的更多细节,请查看我们的以前的文章

We can now add the annotation in a configuration class in our Client application:

我们现在可以在客户端应用程序的配置类中添加注解:

@Configuration
@EnableOAuth2Sso
public class SiteSecurityConfigurer
  extends WebSecurityConfigurerAdapter {
 
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // ...    
    }
}

Any requests that require authentication will be redirected to the Authorization Server. For this to work we also have to define the server properties:

任何需要认证的请求都将被重定向到授权服务器。为了使其发挥作用,我们还必须定义服务器属性。

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

Note that we need to have spring-boot-starter-security in our classpath to find the above configuration working.

注意,我们需要有spring-boot-starter-security在我们的classpath中,才能发现上述配置在工作。

3. Relaying Access Tokens

3.中继访问令牌

While relaying a token, an OAuth2 Client forwards the OAuth2 token received by it to an outgoing resource request.

在转发令牌时,OAuth2客户端会将其收到的OAuth2令牌转发到发出的资源请求中。

Since we’ve declared the @EnableOauth2Sso annotation, Spring Boot adds an OAuth2ClientContext bean in the request scope. Based on this, we can create our own OAuth2RestTemplate in our client application:

由于我们已经声明了@EnableOauth2Sso注解,Spring Boot在请求范围内添加了一个OAuth2ClientContextBean。在此基础上,我们可以在客户端应用程序中创建我们自己的OAuth2RestTemplate

@Bean
public OAuth2RestOperations restOperations(
  OAuth2ProtectedResourceDetails resource, OAuth2ClientContext context) {
    return new OAuth2RestTemplate(resource, context);
}

Once we’ve configured the bean, the context will forward the access token to the requested services and will also refresh the token if it expires.

一旦我们配置了Bean上下文将把访问令牌转发给请求的服务,如果令牌过期,也将刷新它。

4. Relaying an OAuth Token Using the RestTemplate

4.使用RestTemplate转发OAuth令牌

We previously defined a restOperations bean of type OAuth2RestTemplate in our Client application. As a result, we can use the getForObject() method of OAuth2RestTemplate to send a request with the necessary tokens to a protected Resource server from our client.

我们之前在客户端应用程序中定义了一个restOperations类型的OAuth2RestTemplatebean。因此,我们可以使用OAuth2RestTemplategetForObject()方法,从我们的客户端发送一个带有必要令牌的请求到受保护的资源服务器

First, let’s define an endpoint which requires authentication in our Resource Server:

首先,让我们在我们的资源服务器中定义一个需要认证的端点。

@GetMapping("/person")
@PreAuthorize("hasAnyRole('ADMIN', 'USER')")
public @ResponseBody Person personInfo(){        
    return new Person("abir", "Dhaka", "Bangladesh", 29, "Male");       
 }    

This is a simple REST endpoint that returns a JSON representation of a Person object.

这是一个简单的REST端点,返回一个Person对象的JSON表示。

Now, we can send a request from the Client application using the getForObject() method which will relay the token to the Resource Server:

现在,我们可以使用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. Configuring Zuul for Token Relay

5.为令牌中继配置Zuul

If we’d like to relay a token downstream to the proxy services, we can use Spring Cloud Zuul Embedded Reverse Proxy.

如果我们想把令牌中转到下游的代理服务,我们可以使用Spring Cloud Zuul嵌入式反向代理。

First, we need to add the Maven dependency for working with Zuul:

首先,我们需要添加Maven依赖,以便与Zuul一起工作。

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>

Next, we need to add the @EnableZuulProxy annotation on to our configuration class in the Client application:

接下来,我们需要将@EnableZuulProxy注解添加到我们客户端应用程序的配置类中。

@Configuration
@EnableOAuth2Sso
@EnableZuulProxy
public class SiteSecurityConfigurer
  extends WebSecurityConfigurerAdapter {
    //...
}

All that’s left to do is add the Zuul configuration properties to our application.yml file:

剩下的就是把Zuul的配置属性添加到我们的application.yml文件中。

zuul:
  sensitiveHeaders: Cookie,Set-Cookie  
  routes:
    resource:
      path: /api/**
      url: http://localhost:9000
    user: 
      path: /user/**
      url: http://localhost:9000/user

Any request coming to the /api endpoint of the Client application will be redirected to the Resource Server URL. We also need to provide the URL of the user credentials endpoint.

任何进入客户端应用程序的/api端点的请求将被重定向到资源服务器的URL。我们还需要提供用户凭证端点的URL。

6. Conclusion

6.结论

In this quick article, we explored how to use Spring Cloud Security with OAuth2 and Zuul to configure secured authorization and resource servers, as well as how to relay OAuth2 tokens between servers using Oauth2RestTemplate and Embedded Zuul Proxy.

在这篇快速文章中,我们探讨了如何使用Spring Cloud Security与OAuth2和Zuul来配置安全的授权和资源服务器,以及如何使用Oauth2RestTemplate和嵌入式Zuul Proxy在服务器之间中转OAuth2令牌。

As always, the code is available over on GitHub.

一如既往,代码可在GitHub上获得