马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
一、Spring Security 6 与 OAuth 2.0 概述
Spring Security 6是Spring Security的最新主版本,全面支持OAuth 2.1和OpenID Connect 1.0。本文将实战演示怎样构建一个完备的OAuth 2.0授权服务器和资源服务器,实现安全的API认证与授权。
二、项目架构计划
- ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
- │ 客户端应用 │────▶│ OAuth 2.0 │────▶│ 资源服务器 │
- │ (Vue/React) │◀────│ 授权服务器 │◀────│ (REST API) │
- └─────────────────┘ └─────────────────┘ └─────────────────┘
- │ │ │
- └───────────────────────┴───────────────────────┘
- JWT Token 认证流程
复制代码 三、授权服务器搭建
3.1 添加依赖
- <dependencies>
- <dependency>
- <groupId>org.springframework.security</groupId>
- spring-security-oauth2-authorization-server</artifactId>
- <version>1.3.0</version>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- spring-boot-starter-security</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- spring-boot-starter-web</artifactId>
- </dependency>
- </dependencies>
复制代码 3.2 授权服务器设置
- @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); }
- }
- }
复制代码 四、资源服务器搭建
4.1 设置文件
- spring:
- security:
- oauth2:
- resourceserver:
- jwt:
- issuer-uri: http://localhost:9000
- jwk-set-uri: http://localhost:9000/.well-known/jwks.json
复制代码 4.2 安全设置
- @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();
- }
- }
复制代码 4.3 受掩护API示例
- @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"; }
- }
复制代码 五、客户端测试
5.1 获取Token
- 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}
复制代码 5.2 调用API
- curl -H "Authorization: Bearer eyJ..." http://localhost:8081/api/user/profile
- # 返回: {"username":"admin","scopes":["openid","profile","api.read"]}
复制代码 六、最佳实践
- HTTPS:生产情况必须使用TLS
- Token逾期:access_token发起5-15分钟
- PKCE:移动端和SPA必须使用
- 密钥管理:使用Vault等工具存储密钥
七、总结
本文完备演示了Spring Security 6搭建OAuth 2.0授权服务器和资源服务器的全过程。Spring Security 6简化了OAuth 2.0的设置,发起团结Redis实现Token存储,使用数据库存储客户端和用户数据。
免责声明:如果侵犯了您的权益,请联系站长及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金. |