下面我将详细介绍“Spring Security安全框架之记住我功能”的完整攻略,包括步骤、关键代码和示例。希望能够对您有所帮助。
步骤
- 导入相关依赖:在pom.xml文件中添加以下依赖:
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring.security.version}</version>
</dependency>
- 配置Spring Security:在Spring Security配置类的
configure(HttpSecurity http)
方法中添加rememberMe()
方法
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// ...其他配置...
.rememberMe()
.key("mySecretKey") // 自定义的key,用于加密和解密
.userDetailsService(userDetailsService()) // 用户服务
.tokenValiditySeconds(60 * 60 * 24 * 7); // 记住我有效时长,单位为s
}
// ...其他方法...
}
- 在登录页面添加记住我功能:在登录表单中添加一个
<input>
元素,用于用户勾选是否记住登录状态
<form action="/login" method="post">
<input type="text" name="username" placeholder="Username" />
<input type="password" name="password" placeholder="Password" />
<input type="checkbox" name="remember-me" /> 记住我
<input type="submit" value="登录" />
</form>
- 在认证成功后,返回响应头:如果用户勾选了“记住我”选项,则在认证成功后返回一个名为
remember-me
的响应头,该响应头包含了需要在浏览器中保存的记住我token
@PostMapping("/login")
public ResponseEntity<String> login(@RequestParam String username, @RequestParam String password,
@RequestParam(required = false) boolean rememberMe) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
// 进行密码验证
if (passwordEncoder.matches(password, userDetails.getPassword())) {
// 认证成功
// 生成一个remember me token
PersistentRememberMeToken token = new PersistentRememberMeToken(username, UUID.randomUUID().toString(),
new Date(), "mySecretKey");
if (rememberMe) {
// 如果用户勾选了"记住我"选项,则生成一个名为"remember-me"的响应头
HttpHeaders headers = new HttpHeaders();
headers.add("remember-me",
String.format("%s|%s|%s", token.getUsername(), token.getSeries(), token.getTokenValue()));
return new ResponseEntity<>("登录成功!", headers, HttpStatus.OK);
} else {
// 如果用户未勾选"记住我"选项,则直接返回登录成功的消息
return new ResponseEntity<>("登录成功!", HttpStatus.OK);
}
} else {
// 认证失败
return new ResponseEntity<>("用户名或密码错误!", HttpStatus.UNAUTHORIZED);
}
}
- 配置TokenRepository:在Spring配置中添加一个名为
tokenRepository
的bean,用于将remember me token保存到数据库或者内存中
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private DataSource dataSource;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// ...其他配置...
.rememberMe()
.key("mySecretKey") // 自定义的key,用于加密和解密
.userDetailsService(userDetailsService()) // 用户服务
.tokenValiditySeconds(60 * 60 * 24 * 7) // 记住我有效时长,单位为s
.tokenRepository(tokenRepository()); // token存储方式
}
@Bean
public PersistentTokenRepository tokenRepository() {
// 使用默认的JdbcTokenRepositoryImpl
JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
jdbcTokenRepository.setDataSource(dataSource);
return jdbcTokenRepository;
}
// ...其他方法...
}
示例
下面是两个简单的示例,一个是将remember me token保存到内存中,另一个是将remember me token保存到数据库中。
内存方式保存remember me token
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private Map<String, PersistentRememberMeToken> tokens = new ConcurrentHashMap<>();
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// ...其他配置...
.rememberMe()
.key("mySecretKey") // 自定义的key,用于加密和解密
.userDetailsService(userDetailsService()) // 用户服务
.tokenValiditySeconds(60 * 60 * 24 * 7) // 记住我有效时长,单位为s
.tokenRepository(new TokenRepository() {
@Override
public void createNewToken(PersistentRememberMeToken token) {
tokens.put(token.getSeries(), token);
}
@Override
public void updateToken(String series, String tokenValue, Date lastUsed) {
PersistentRememberMeToken token = tokens.get(series);
if (token != null) {
token.setTokenValue(tokenValue);
token.setDate(lastUsed);
}
}
@Override
public PersistentRememberMeToken getTokenForSeries(String seriesId) {
return tokens.get(seriesId);
}
@Override
public void removeUserTokens(String username) {
tokens.values().removeIf(token -> token.getUsername().equals(username));
}
});
}
// ...其他方法...
}
数据库方式保存remember me token
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private DataSource dataSource;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// ...其他配置...
.rememberMe()
.key("mySecretKey") // 自定义的key,用于加密和解密
.userDetailsService(userDetailsService()) // 用户服务
.tokenValiditySeconds(60 * 60 * 24 * 7) // 记住我有效时长,单位为s
.tokenRepository(new JdbcTokenRepositoryImpl() {{
setDataSource(dataSource);
}});
}
// ...其他方法...
}
这两个示例都是实现了TokenRepository接口并在configure(HttpSecurity http)
方法中配置了tokenRepository()
方法,区别在于内存方式的实现没有通过数据库存储,而是使用了一个ConcurrentHashMap
作为存储方式。如果需要使用数据库存储,那么只需要在Spring配置中配置一个DataSource
并使用JdbcTokenRepositoryImpl
作为TokenRepository即可。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring Security安全框架之记住我功能 - Python技术站