Lac*_*lev 5 spring spring-security spring-boot
我的问题主要针对 Spring Boot 3.x/Spring Security 6.x,但也可能适用于旧版本。我有一个带有表单登录的小项目。这是一个示例配置。
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.
...
formLogin().
loginPage("/users/login").
...
return http.build();
}
@Bean
public UserDetailsService userDetailsService(UserRepository userRepository) {
return new AppUserDetailsService(userRepository);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Run Code Online (Sandbox Code Playgroud)
确实没什么特别的,而且工作得很好。我还有一张登记表。它也工作正常,并且用户已在数据库中正确创建。之后就可以登录了。到目前为止,一切都很好。
我想做的最后一件事是在注册后立即自动登录用户。在早期的 Srping 版本中,这使用了类似的代码,可能是受到这里的启发:
@Override
public void createAccount(UserRegistrationDTO userRegistrationDTO) {
UserEntity userEntity = new UserEntity();
userEntity.
setFirstName(userRegistrationDTO.getFirstName()).
setLastName(userRegistrationDTO.getLastName()).
setEmail(userRegistrationDTO.getEmail()).
setPassword(passwordEncoder.encode(userRegistrationDTO.getPassword()));
userRepository.save(userEntity);
var userDetails = userDetailsService.loadUserByUsername(userRegistrationDTO.getEmail());
Authentication authentication = new UsernamePasswordAuthenticationToken(
userDetails,
userDetails.getPassword(),
userDetails.getAuthorities()
);
SecurityContextHolder.
getContext().
setAuthentication(authentication);
}
Run Code Online (Sandbox Code Playgroud)
这在 3.x/6.x 中不再有效
我的猜测是我需要使用AuthenticationManager,但我不确定如何注入正确的本地AuthenticationManager以及哪个安全过滤器链。我什至不知道如何使用AuthenticationManagerResolver<HttpServletRequest>如果这是解决它的方法......
我已经成功地通过在 Spring 上下文中使用HttpServletRequest.login(userName, password)委托来实现该功能,并且可能还执行数百万其他操作。AuthenticationManager但我有一种感觉,我正在做一些非常错误的事情。
实现这个简单功能的正确方法是什么?
首先,非常感谢 Marcus Hert da Coregio 为我指明了正确的方向。事实上,这是这里描述的 Spring security 6 中的一个重大变化。安全上下文存储库不再是HttpSessionSecurityContextRepository,而是DelegatingSecurityContextRepository。此处对此进行了描述。
我所做的是将其公开DelegatingSecurityContextRepository为 bean,如迁移文档中所暗示的:
@Bean
public SecurityContextRepository securityContextRepository() {
return new DelegatingSecurityContextRepository(
new RequestAttributeSecurityContextRepository(),
new HttpSessionSecurityContextRepository()
);
}
Run Code Online (Sandbox Code Playgroud)
后来我的安全配置以类似的方式扩展:
@Bean
public SecurityFilterChain filterChain(HttpSecurity http,
SecurityContextRepository securityContextRepository) throws Exception {
http.
...
.and().
securityContext().
securityContextRepository(securityContextRepository);
return http.build();
}
Run Code Online (Sandbox Code Playgroud)
自动登录已修复,如下所示(重要的一行是将上下文保存在存储库中):
@Override
public void createAccount(UserRegistrationDTO userRegistrationDTO,
HttpServletRequest request,
HttpServletResponse response) {
...
SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
.getContextHolderStrategy();
SecurityContext context = securityContextHolderStrategy.createEmptyContext();
context.setAuthentication(authentication);
securityContextHolderStrategy.setContext(context);
securityContextRepository.saveContext(context, request, response);
}
Run Code Online (Sandbox Code Playgroud)
如果它在迁移到 Spring Security 6 后停止工作,则可能与需要显式保存SecurityContext.
这意味着您应该通过调用显式保存上下文SecurityContextRepository:
SecurityContext context = SecurityContextHolder.createEmptyContext();
context.setAuthentication(authentication);
SecurityContextHolder.setContext(context);
securityContextRepository.saveContext(request, response, context);
Run Code Online (Sandbox Code Playgroud)
securityContextRepository通常在哪里HttpSessionSecurityContextRepository。
| 归档时间: |
|
| 查看次数: |
2678 次 |
| 最近记录: |