Spring Security 6 + OAuth 2.0实战:构建企业级认证授权系统
<h2>一、Spring Security 6 与 OAuth 2.0 概述</h2><p>Spring Security 6是Spring Security的最新主版本,全面支持OAuth 2.1和OpenID Connect 1.0。本文将实战演示如何构建一个完整的OAuth 2.0授权服务器和资源服务器,实现安全的API认证与授权。</p>
<h2>二、项目架构设计</h2>
<pre><code>┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 客户端应用 │────▶│OAuth 2.0 │────▶│ 资源服务器 │
│(Vue/React) │◀────│授权服务器 │◀────│(REST API) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
└───────────────────────┴───────────────────────┘
JWT Token 认证流程</code></pre>
<h2>三、授权服务器搭建</h2>
<h3>3.1 添加依赖</h3>
<pre><code><dependencies>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-authorization-server</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies></code></pre>
<h3>3.2 授权服务器配置</h3>
<pre><code>@Configuration
@EnableWebSecurity
public class AuthorizationServerConfig {
@Bean @Order(1)
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
http.getConfigurer(OAuth2AuthorizationServerConfigurer.class).oidc(Customizer.withDefaults());
return http.build();
}
@Bean @Order(2)
public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(auth -> auth.requestMatchers("/login").permitAll().anyRequest().authenticated())
.formLogin(Customizer.withDefaults());
return http.build();
}
@Bean
public RegisteredClientRepository registeredClientRepository() {
RegisteredClient client = RegisteredClient.withId(UUID.randomUUID().toString())
.clientId("my-client").clientSecret("{noop}my-secret")
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
.redirectUri("http://127.0.0.1:8080/login/oauth2/code/my-client")
.scope(OidcScopes.OPENID).scope(OidcScopes.PROFILE).scope("api.read").scope("api.write")
.clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build()).build();
return new InMemoryRegisteredClientRepository(client);
}
@Bean
public JWKSource<SecurityContext> jwkSource() {
RSAKey rsaKey = generateRsaKey();
return (jwkSelector, context) -> jwkSelector.select(new JWKSet(rsaKey));
}
private static RSAKey generateRsaKey() {
try {
KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
return new RSAKey.Builder((RSAPublicKey)keyPair.getPublic())
.privateKey((RSAPrivateKey)keyPair.getPrivate()).keyID(UUID.randomUUID().toString()).build();
} catch (Exception e) { throw new IllegalStateException(e); }
}
}</code></pre>
<h2>四、资源服务器搭建</h2>
<h3>4.1 配置文件</h3>
<pre><code>spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: http://localhost:9000
jwk-set-uri: http://localhost:9000/.well-known/jwks.json</code></pre>
<h3>4.2 安全配置</h3>
<pre><code>@Configuration
@EnableWebSecurity
public class ResourceServerConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/public/**").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated())
.oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()));
return http.build();
}
}</code></pre>
<h3>4.3 受保护API示例</h3>
<pre><code>@RestController
@RequestMapping("/api")
public class ApiController {
@GetMapping("/user/profile")
public Map<String, Object> userProfile(@AuthenticationPrincipal Jwt jwt) {
return Map.of("username", jwt.getSubject(), "scopes", jwt.getClaimAsStringList("scope"));
}
@GetMapping("/admin/data")
@PreAuthorize("hasRole('ADMIN')")
public String adminData() { return "Admin only data"; }
}</code></pre>
<h2>五、客户端测试</h2>
<h3>5.1 获取Token</h3>
<pre><code>curl -X POST http://localhost:9000/oauth2/token -H "Content-Type: application/x-www-form-urlencoded" -u "my-client:my-secret" -d "grant_type=client_credentials" -d "scope=api.read"
# 返回: {"access_token":"eyJ...","token_type":"Bearer","expires_in":300}</code></pre>
<h3>5.2 调用API</h3>
<pre><code>curl -H "Authorization: Bearer eyJ..." http://localhost:8081/api/user/profile
# 返回: {"username":"admin","scopes":["openid","profile","api.read"]}</code></pre>
<h2>六、最佳实践</h2>
<ol>
<li><strong>HTTPS</strong>:生产环境必须使用TLS</li>
<li><strong>Token过期</strong>:access_token建议5-15分钟</li>
<li><strong>PKCE</strong>:移动端和SPA必须使用</li>
<li><strong>密钥管理</strong>:使用Vault等工具存储密钥</li>
</ol>
<h2>七、总结</h2>
<p>本文完整演示了Spring Security 6搭建OAuth 2.0授权服务器和资源服务器的全过程。Spring Security 6简化了OAuth 2.0的配置,建议结合Redis实现Token存储,使用数据库存储客户端和用户数据。</p>
</div>
<div id="MySignature" role="contentinfo">
---
📌 **如果觉得文章对你有帮助,欢迎点赞👍收藏⭐!**
💬 有问题或建议?欢迎在评论区留言讨论~
🔗 更多技术干货请关注作者:弥烟袅绕
📚 本文地址:https://www.cnblogs.com/czlws/p/19846673/spring-security-oauth2-tutorial-2026<br><br>
来源:https://www.cnblogs.com/czlws/p/19846673/spring-security-oauth2-tutorial-2026
頁:
[1]