Spring Boot实现单点登录
什么是单点登录
单点登录(Single Sign-On,简称SSO)是一种让用户只需登录一次,就能访问多个应用系统的认证技术。用户只需要使用一组凭证(用户名和密码)登录系统,然后就可以无需再次输入凭证,在其他受信任的系统中自动登录。
Spring Boot单点登录实现方案
在Spring Boot中实现单点登录有多种方案可供选择,其中一种常用的方案是使用基于Token的认证机制。下面我们将使用Spring Security和JSON Web Token(JWT)来实现单点登录。
1. 创建Spring Boot项目
首先,我们需要创建一个Spring Boot项目。你可以使用Spring Initializer( init`命令进行创建。
2. 添加依赖
在pom.xml
文件中添加以下依赖:
<dependencies>
<!-- Spring Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- JSON Web Token -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.2</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.2</version>
<scope>runtime</scope>
</dependency>
</dependencies>
3. 配置Spring Security
在application.properties
文件中添加以下配置:
spring.security.user.name=admin
spring.security.user.password=admin
创建一个WebSecurityConfig
类,继承WebSecurityConfigurerAdapter
,并添加@EnableWebSecurity
注解。在该类中,我们将配置Spring Security,包括允许对某些URL进行匿名访问和配置基于JWT的认证策略。
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
@Autowired
private JwtRequestFilter jwtRequestFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/authenticate").permitAll()
.anyRequest().authenticated()
.and().exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint)
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin")
.password("$2a$10$Hmz2NtTzJ4O4KZBCSjIX3eYVwJ4T9rP1iFYjOojjGyM1zJt1b6UvW")
.roles("ADMIN");
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
}
4. 创建JWT工具类
创建一个JwtUtil
类,用于处理JWT的生成、解析和验证。
@Component
public class JwtUtil {
private final String SECRET_KEY = "secret";
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
return createToken(claims, userDetails.getUsername());
}
private String createToken(Map<String, Object> claims, String subject) {
return Jwts.builder().setClaims(claims).setSubject(subject)
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10))
.signWith(SignatureAlgorithm.HS256, SECRET_KEY).compact();
}
public String extractUsername(String token) {
return extractClaim(token, Claims::getSubject);
}
public Date extractExpiration(String token) {
return extractClaim(token, Claims::getExpiration);
}
private <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
final Claims claims = extractAllClaims(token);
return claimsResolver.apply(claims);
}
private