OAuth2.0 集成
约 1247 字大约 4 分钟
布欧-Lewyon
2026-05-16
首页 › Spring Boot › 安全入门 › OAuth2.0 集成
OAuth2.0 是业界标准的授权框架,Spring Security 通过 spring-boot-starter-oauth2-client 和 spring-boot-starter-oauth2-resource-server 提供开箱即用的支持。本节覆盖社交登录(第三方登录)和资源服务器(JWT Bearer Token 保护 API)两种典型场景。
OAuth2.0 角色
场景一:社交登录(OAuth2 Client)
让用户通过 GitHub / Google / 微信等第三方账号登录。
起步依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>配置 GitHub OAuth App
在 GitHub 的 Settings → Developer settings → OAuth Apps 中注册应用,回调地址设为 http://localhost:8080/login/oauth2/code/github。
spring:
security:
oauth2:
client:
registration:
github:
client-id: ${GITHUB_CLIENT_ID}
client-secret: ${GITHUB_CLIENT_SECRET}
scope: read:user,user:email
google:
client-id: ${GOOGLE_CLIENT_ID}
client-secret: ${GOOGLE_CLIENT_SECRET}安全配置
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/", "/login", "/oauth2/**").permitAll()
.anyRequest().authenticated()
)
.oauth2Login(Customizer.withDefaults()) // 启用 OAuth2 登录
.logout(logout -> logout
.logoutSuccessUrl("/")
.invalidateHttpSession(true));
return http.build();
}
}启动后访问 http://localhost:8080,页面会自动跳转到 GitHub/Google 授权页,授权通过后重定向回应用。
获取用户信息
@RestController
public class UserController {
@GetMapping("/user")
public Map<String, Object> user(@AuthenticationPrincipal OAuth2User principal) {
// OAuth2User 包含第三方平台返回的用户属性
return Map.of(
"name", principal.getAttribute("name"),
"email", principal.getAttribute("email"),
"avatar", principal.getAttribute("avatar_url")
);
}
}自定义用户注册逻辑
社交登录成功后的处理通过 OAuth2UserService 自定义:
@Component
public class CustomOAuth2UserService extends DefaultOAuth2UserService {
@Autowired
private UserRepository userRepository;
@Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) {
OAuth2User oAuth2User = super.loadUser(userRequest);
String provider = userRequest.getClientRegistration().getRegistrationId(); // github/google
String providerId = oAuth2User.getName();
// 查找或创建本地用户
User user = userRepository.findByProviderAndProviderId(provider, providerId)
.orElseGet(() -> registerNewUser(provider, providerId, oAuth2User));
return oAuth2User;
}
}场景二:资源服务器(API 保护)
已有 JWT Token(由外部授权服务器签发),Spring Boot API 只需要验证 Token 而不需要管理用户。
起步依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>配置 JWT 验证(对称密钥)
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: https://auth.example.com
# 或直接指定 JWK Set URI(密钥轮换友好)
# jwk-set-uri: https://auth.example.com/.well-known/jwks.json非对称密钥(本地验证,无外部授权服务器)
spring:
security:
oauth2:
resourceserver:
jwt:
public-key-location: classpath:public.pem安全配置
@Configuration
@EnableWebSecurity
public class ResourceServerConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable())
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/public/**").permitAll()
.requestMatchers("/api/admin/**").hasAuthority("SCOPE_admin")
.anyRequest().authenticated()
)
.oauth2ResourceServer(oauth2 -> oauth2
.jwt(Customizer.withDefaults())); // 自动校验 Bearer Token
return http.build();
}
}Spring Security 会自动从请求头 Authorization: Bearer <token> 中提取 JWT,调用配置的 JwtDecoder 验证签名、过期时间和 issuer。
自定义 JWT 解析
@Component
public class CustomJwtAuthenticationConverter implements Converter<Jwt, AbstractAuthenticationToken> {
@Override
public AbstractAuthenticationToken convert(Jwt jwt) {
// 从 JWT claims 中提取角色
Collection<String> roles = jwt.getClaimAsStringList("roles");
Collection<GrantedAuthority> authorities = roles.stream()
.map(role -> new SimpleGrantedAuthority("ROLE_" + role))
.toList();
return new JwtAuthenticationToken(jwt, authorities);
}
}@Bean
public SecurityFilterChain filterChain(HttpSecurity http, CustomJwtAuthenticationConverter converter) {
http
.oauth2ResourceServer(oauth2 -> oauth2
.jwt(jwt -> jwt.jwtAuthenticationConverter(converter)));
return http.build();
}OAuth2.0 授权模式对比
| 授权模式 | 适用场景 | 流程 |
|---|---|---|
| 授权码(Authorization Code) | 第三方 Web 登录(最安全) | 用户浏览器跳转 → 授权服务器 → 回调 → 后端换 Token |
| 客户端凭证(Client Credentials) | 服务间调用(机器对机器) | 客户端直接用 client_id + secret 换 Token |
| 隐式模式(已废弃) | 纯前端应用 | 安全性不足,已被 PKCE 替代 |
| PKCE | 移动端 / SPA | 授权码 + 动态密钥,安全性优于隐式模式 |
小结
- OAuth2 Client:
spring-boot-starter-oauth2-client实现社交登录,支持 GitHub/Google/微信等第三方认证。 - OAuth2 Resource Server:
spring-boot-starter-oauth2-resource-server保护 API 端点,自动校验 JWT Bearer Token。 - 授权码模式是 Web 登录推荐方式;客户端凭证模式用于服务间调用。
- 资源服务器不管理用户——信任授权服务器的 Token,职责分离。
- 易错:
client-secret必须通过环境变量注入,禁止硬编码。issuer-uri配置后 Spring Security 会自动从授权服务器的/.well-known/openid-configuration端点获取公钥——如果授权服务器不可达,应用启动会失败。资源服务器的 JWT 和客户端的 JWT 使用同一套spring.security.oauth2.resourceserver.jwt配置,两者不可同时使用不同密钥源?可以——通过自定义JwtDecoderBean 覆盖。 - 思考任务:① 注册 GitHub OAuth App,集成
oauth2-client实现社交登录;② 创建独立认证服务签发 JWT,在一个新应用中使用oauth2-resource-server验证并保护 API。
上一节:JWT 认证与登录注销
下一节:生产部署
