Spring Boot 实现单点登录
以下是基于 Spring Boot 实现单点登录(SSO)的代码示例,结合 OAuth2.0 和 JWT 方案,适用于微服务架构或独立系统集成。代码分为 认证服务器(Auth Server)、资源服务器(Resource Server) 和 客户端配置 三部分,并附详细说明。
1. 认证服务器(Auth Server)
负责用户认证和令牌颁发,使用 Spring Security OAuth2 和 JWT。
依赖配置(pom.xml)
<dependencies>
<!-- Spring Security OAuth2 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-authorization-server</artifactId>
</dependency>
<!-- JWT 支持 -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<!-- Redis 用于令牌存储 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
</dependencies>认证服务器配置类
@Configuration
@EnableAuthorizationServer
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("client-app") // 客户端ID
.secret("{noop}secret") // 客户端密钥(未加密)
.authorizedGrantTypes("authorization_code", "refresh_token", "password")
.scopes("read", "write") // 权限范围
.redirectUris(" http://localhost:8081/login/oauth2/code/client-app ");
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints
.authenticationManager(authenticationManager)
.tokenStore(tokenStore())
.accessTokenConverter(jwtAccessTokenConverter());
}
@Bean
public TokenStore tokenStore() {
return new RedisTokenStore(redisTemplate.getConnectionFactory());
}
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey("your-secret-key"); // JWT签名密钥
return converter;
}
}Spring Security 配置
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/oauth/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().permitAll();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}2. 资源服务器(Resource Server)
保护受控资源,验证令牌有效性。
依赖配置(pom.xml)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>资源服务器配置类
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/api/public/**").permitAll()
.antMatchers("/api/**").authenticated();
}
@Bean
public JwtDecoder jwtDecoder() {
return NimbusJwtDecoder.withSecretKey(
new SecretKeySpec("your-secret-key".getBytes(), "HMACSHA256")
).build();
}
}受保护资源接口
@RestController
@RequestMapping("/api")
public class ResourceController {
@GetMapping("/user")
public String getUser(Principal principal) {
return "Hello, " + principal.getName();
}
}3. 客户端应用配置
使用 OAuth2 客户端库接入认证服务器。
application.yml 配置
spring:
security:
oauth2:
client:
registration:
sso:
client-id: client-app
client-secret: secret
authorization-grant-type: authorization_code
redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
scope: read,write
provider:
sso:
issuer-uri: http://localhost:8080 # 认证服务器地址Spring Security 配置
@Configuration
@EnableWebSecurity
public class ClientSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.oauth2Login();
}
}4. 运行与测试
启动服务:依次启动认证服务器(8080 端口)、资源服务器(8081 端口)和客户端应用(8082 端口)。
访问流程:
用户访问客户端应用的受保护资源(如
http://localhost:8082/api/user)。客户端重定向到认证服务器登录页面。
登录成功后返回令牌,客户端通过令牌访问资源服务器。
关键点说明
OAuth2 授权模式:支持
authorization_code(推荐)、password等模式。JWT 令牌:自包含、无状态,适合微服务场景。
Redis 存储:用于管理令牌状态(如吊销)。
跨域问题:需配置 CORS 过滤器。
完整代码可参考 Spring Security OAuth2 官方文档 或上述示例。
Spring Boot 实现单点登录
https://uniomo.com/archives/spring-boot-shi-xian-dan-dian-deng-lu