1. 概述
在这篇文章中,我们将深入探讨 Spring Security 中的 @EnableResourceServer
和 @EnableOAuth2Sso
注解。
首先会解释 OAuth2 客户端(Client)和资源服务器(Resource Server)的区别。然后介绍这两个注解的作用,并通过一个结合 Zuul 和简单 API 的示例,展示它们的实际用法。
本文假设你已经对 Zuul 和 OAuth2 有一定的了解。如果你是新手,建议先阅读我们的 Zuul 快速入门 和 OAuth2 使用指南。
2. OAuth2 客户端 vs 资源服务器
在 OAuth2 协议中定义了四种角色(RFC 6749),我们需要重点关注以下两个:
✅ 资源服务器(Resource Server)
需要访问令牌才能允许访问其受保护资源的服务组件。
✅ 客户端(Client)
能够从授权服务器获取访问令牌的应用实体。
使用 @EnableResourceServer
或 @EnableOAuth2Sso
注解,可以快速将我们的应用配置为以上两种角色之一:
@EnableResourceServer
:让应用成为资源服务器 ✅
Spring 会自动配置如OAuth2AuthenticationProcessingFilter
等核心组件,用于处理 OAuth2 请求验证。@EnableOAuth2Sso
:使应用成为 OAuth2 客户端 ✅
配置OAuth2ClientAuthenticationProcessingFilter
等组件,用于与授权服务器交互以获取访问令牌。
🔍 查看源码可更深入了解:
接下来我们构建两个应用来演示这两个注解的使用场景:
- Zuul 网关应用(边缘节点):使用
@EnableOAuth2Sso
,负责用户认证并转发请求。 - API 应用(资源服务):使用
@EnableResourceServer
,验证访问令牌后提供受保护资源。
3. Zuul 应用 —— @EnableOAuth2Sso
下面是 Zuul 应用的配置类示例:
@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("/");
}
}
📌 注意事项:
- 使用
@EnableOAuth2Sso
后,Spring 会自动注册OAuth2TokenRelayFilter
,它会从用户会话中取出访问令牌,并向下传递。 - 使用
@Order(0)
是为了确保当前安全配置优先于其他自动配置的安全过滤器链。
⚠️ 坑点提醒:如果同时使用了 @EnableResourceServer
,默认情况下它的过滤器顺序(order=3)会高于当前配置(order=100),可能会导致认证逻辑混乱。
下面是相关的 YAML 配置片段:
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
🎯 配置说明:
zuul.routes
:定义路由规则,控制哪些路径由哪个服务处理。security.oauth2.client
:指定授权服务器地址、客户端 ID 和密钥等信息。jwt.keyValue
:使用对称加密方式解析 JWT。
4. API 应用 —— @EnableResourceServer
下面是资源服务器的实现代码:
@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();
}
}
这是一个非常简单的 REST 接口,返回当前用户的名称。
对应配置文件如下:
security:
basic:
enabled: false
oauth2:
resource:
jwt:
keyValue: "abc"
id: fooScope
service-id: ${PREFIX:}resource
🔑 关键点:
- 必须携带有效的 OAuth2 访问令牌才能访问此接口。
- 在网关层完成认证后,访问令牌会被传递到资源服务器进行校验。
5. 总结
这篇文章详细讲解了 @EnableOAuth2Sso
和 @EnableResourceServer
的用途及区别,并通过 Zuul + Resource Server 的实际例子展示了它们如何协同工作。
💡 示例项目完整代码可在 GitHub 获取。
本地运行时可通过如下地址测试:
http://192.168.1.67:8765/resource-server-mvc-1
📌 一句话总结:
@EnableOAuth2Sso
:让应用变成 OAuth2 客户端,负责登录认证。@EnableResourceServer
:让应用变成资源服务器,负责资源保护和权限校验。