1. 概述
在本教程中,我們將討論 Spring Security 中的 @EnableResourceServer 和 @EnableOAuth2Sso 註解。
我們將首先解釋 OAuth2 Client 和 OAuth2 Resource Server 之間的差異。之後,我們將討論這些註解能為我們做什麼,並提供一個使用 Zuul 和一個簡單 API 的示例。
為了本文的目的,我們假設您已經具備了對 Zuul 和 OAuth2 的一定經驗。
如果您沒有相關經驗,或者認為對其中任何一個進行回顧會有所幫助,請參考我們關於 Zuul 的快速概述以及關於 OAuth2 的指南。
2. OAuth2 客户端和資源服務器
OAuth2 中有四種不同的 roles 需要考慮:
- Resource Owner — 一個能夠授權其受保護資源的實體
- Authorization Server — 向 Clients 授予訪問令牌,在成功驗證 Resource Owners 並獲取其授權後
- Resource Server — 一個需要訪問令牌才能允許訪問其資源的組件
- Client — 一個能夠從授權服務器獲取訪問令牌的實體
使用 @EnableResourceServer 或 @EnableOAuth2Sso 註解,指示 Spring 配置組件,將我們的應用程序轉換為上述兩種角色之一。
@EnableResourceServer 註解使我們的應用程序以 Resource Server 的方式運行,通過配置 OAuth2AuthenticationProcessingFilter 以及其他同樣重要的組件 。
查看 ResourceServerSecurityConfigurer 類,以更好地瞭解幕後配置的內容。
相反,@EnableOAuth2Sso 註解將我們的應用程序轉換為 OAuth2 客户端。它指示 Spring 配置 OAuth2ClientAuthenticationProcessingFilter,以及我們的應用程序需要具備從授權服務器獲取訪問令牌的其他組件。
查看 SsoSecurityConfigurer 類,以獲取 Spring 配置對我們所做的事情的更多詳細信息。
通過結合使用這些註解和一些屬性,我們可以快速啓動應用程序。讓我們創建兩個不同的應用程序,以查看它們在行動中的樣子,以及它們如何互補:
- 我們的第一個應用程序將是我們的邊緣節點,一個簡單的 Zuul 應用程序,它將使用 @EnableOAuth2Sso 註解。它將負責驗證用户(藉助 Authorization Server)並將傳入請求委派給其他應用程序
- The second application is going to use @EnableResourceServer annotation and will allow access to protected resources if the incoming requests contain a valid OAuth2 access token
3. Zuul – >
Let’s start by creating a Zuul application that is going to act as our edge node and is going to be responsible for authenticating users using an OAuth2 :
@Configuration
@EnableZuulProxy
@EnableOAuth2Sso
@Order(value = 0)
public class AppConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private ResourceServerTokenServices
resourceServerTokenServices;
@Override
public void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/authorization-server-1/**",
"/login").permitAll()
.anyRequest().authenticated().and()
.logout().permitAll().logoutSuccessUrl("/");
}
}
Annotating our Zuul application with also notifies Spring to configure an filter. This filter retrieves previously obtained access tokens from users’ HTTP sessions and propagates them downstream.
Note that we’re also using the annotation in our AppConfiguration configuration class. This is to make sure that created by our take precedence over created by other .
For example, we could annotate our Zuul application with to support both HTTP Session identifiers and OAuth2 access tokens. However, doing so creates new that by default, take precedence over the ones created by AppConfiguration class. This happens because , a configuration class triggered by , specifies a default of 3 while has a default of 100.
Before we move onto our Resource Server, we need to configure some properties:
zuul:
routes:
resource-server-mvc-1: /resource-server-mvc-1/**
authorization-server-1:
sensitiveHeaders: Authorization
path: /authorization-server-1/**
stripPrefix: false
add-proxy-headers: true
security:
basic:
enabled: false
oauth2:
sso:
loginPath: /login
client:
accessTokenUri: http://localhost:8769/authorization-server-1/oauth/token
userAuthorizationUri: /authorization-server-1/oauth/authorize
clientId: fooClient
clientSecret: fooSecret
resource:
jwt:
keyValue: "abc"
id: fooScope
serviceId: ${PREFIX:}resource
Without going into too much detail, using this config, we are:
- Configuring our Zuul routes and saying which headers should be added/removed before sending requests downstream.
- Setting some OAuth2 properties for our application to be able to communicate with our and configuring with encryption.
4. API – @EnableResourceServer
現在我們已經部署了我們的 Zuul 應用程序,現在讓我們創建我們的 Resource Server:
@SpringBootApplication
@EnableResourceServer
@Controller
@RequestMapping("/")
class ResourceServerApplication {
public static void main(String[] args) {
SpringApplication.run(ResourceServerApplication.class, args);
}
@RequestMapping(method = RequestMethod.GET)
@ResponseBody
public String helloWorld(Principal principal) {
return "Hello " + principal.getName();
}
}
這是一個簡單的應用程序,它暴露了一個單個端點以返回發起請求的 name 以及 Principal。
最後,讓我們配置一些屬性:
security:
basic:
enabled: false
oauth2:
resource:
jwt:
keyValue: "abc"
id: fooScope
service-id: ${PREFIX:}resource
請記住,我們需要一個有效的訪問令牌(它存儲在用户在邊緣節點的 HTTP 會話中)才能訪問我們的 Resource Server 端點。
5. 結論
在本文中,我們解釋了 @EnableOAuth2Sso 和 @EnableResourceServer 註解之間的區別。我們還展示瞭如何使用它們,並通過一個實際示例,使用了 Zuul 和一個簡單的 API。
在本地運行時,我們可以運行和測試該應用程序,網址是 http://192.168.1.67:8765/resource-server-mvc-1。