java - 使用 DaoAuthenticationProvider 注册后自动登录
问题描述
在我的 spring-boot 应用程序中成功注册后,我尝试实现自动登录。
为了存储用户数据,我使用 Hibernate,而对于身份验证,我使用 DaoAuthenticationProvider。已经在数据库中的用户的登录效果很好,新用户的注册也很好。只有注册后的自动登录不起作用。
作为用户名,我使用用户的电子邮件。我尝试了几种在互联网上推荐的不同方法。他们都没有工作。包括这些:
成功注册后自动登录 如何使用 DaoAuthenticationProvider https://www.baeldung.com/spring-security-auto-login-user-after-registration以编程方式使用 Spring Security 对用户进行身份验证
我的 WebSecurityConifig 类:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
@Autowired
private UserService userService;
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth
.userDetailsService(userService)
.passwordEncoder(bCryptPasswordEncoder);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.
authorizeRequests()
.antMatchers("/login", "/console/**", "/registerNewUser/**", "/resources/**", "/css/**").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated().and().csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.ignoringAntMatchers("/console/**")
// Request zum Aufruf der Login-Seite
.and().formLogin().loginPage("/login").failureUrl("/login?error=true").permitAll()
.defaultSuccessUrl("/")
.usernameParameter("email")
.passwordParameter("password")
.and().logout().permitAll()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/login?logout");
http.headers().frameOptions().sameOrigin().disable();
http.sessionManagement().maximumSessions(1).sessionRegistry(sessionRegistry());
}
@Override
public void configure(WebSecurity web) {
web
.ignoring()
.antMatchers("/resources/static/**", "/css/**", "/js/**", "/img/**");
}
@Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider auth = new DaoAuthenticationProvider();
auth.setUserDetailsService(userService);
auth.setPasswordEncoder(bCryptPasswordEncoder);
return auth;
}
@Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
@Bean
public ServletListenerRegistrationBean<HttpSessionEventPublisher> httpSessionEventPublisher() {
return new ServletListenerRegistrationBean<HttpSessionEventPublisher>(new HttpSessionEventPublisher());
}
@Bean(name = BeanIds.AUTHENTICATION_MANAGER)
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
我的控制器注册一个新用户:
@Controller
public class AccRegistrationController {
@Autowired
private UserService userService;
@Autowired
private RoleService roleService;
@Autowired
private BCryptPasswordEncoder passwordEncoder;
@Autowired
private UserValidator userValidator;
@Autowired
private AuthenticationManager authenticationManager;
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.setValidator(userValidator);
}
@GetMapping("registerNewUser")
public String registerUser(Model model, HttpServletRequest request) {
model.addAttribute("user", new User());
request.getSession();
return "accountRegistration/registration";
}
@PostMapping("registerNewUser")
public String registerAccount(HttpServletRequest request, @Valid @ModelAttribute("user") User user, BindingResult bindingResult, Model model) {
if (bindingResult.hasErrors()) {
model.addAttribute("user", user);
return "accountRegistration/registration";
}
user.setPassword(passwordEncoder.encode(user.getPassword()));
user.setActivated(false);
user.setRoles(roleService.findAllByRolename("ROLE_USER"));
userService.saveUser(user);
UsernamePasswordAuthenticationToken token = new
UsernamePasswordAuthenticationToken(user.getEmail(), user.getPassword());
request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());
token.setDetails(new WebAuthenticationDetails(request));
Authentication authentication = authenticationManager.authenticate(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
return "redirect:registerNewUser?success";
}
}
我的用户服务类:
@Service
public class UserService implements UserDetailsService {
private static final Logger logger = LoggerFactory.getLogger(Data.class);
@Autowired
private UserRepository userRepository;
@Autowired
private BCryptPasswordEncoder passwordEncoder;
@Autowired
private SessionRegistry sessionRegistry;
/* creates new user object and returns it with an auto generated id */
public User saveUser(User user) {
return userRepository.save(user);
}
public List<User> getAllUsers() {
return userRepository.findAll();
}
public Optional<User> findUser(Integer id) {
return userRepository.findById(id);
}
public User getUserByEmail(String email) {
return userRepository.findUserByEmail(email);
}
public User getOne(Integer id) {
return userRepository.getOne(id);
}
public User getCurrentUser() {
return getUserByEmail(((org.springframework.security.core.userdetails.User) SecurityContextHolder.getContext()
.getAuthentication().getPrincipal()).getUsername());
}
public org.springframework.security.core.userdetails.User getCurrentUserDetails() {
return (org.springframework.security.core.userdetails.User) SecurityContextHolder.getContext()
.getAuthentication().getPrincipal();
}
@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
User user = userRepository.findUserByEmail(email);
if (Objects.isNull(user)) {
throw new UsernameNotFoundException("Could not find the user for username " + email);
}
List<GrantedAuthority> grantedAuthorities = getUserAuthorities(user.getRoles());
return new org.springframework.security.core.userdetails.User(user.getEmail(), user.getPassword(),
user.isEnabled(), true, true, user.isEnabled(), grantedAuthorities);
}
private List<GrantedAuthority> getUserAuthorities(Set<Role> roleSet) {
List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
for (Role role : roleSet) {
grantedAuthorities.add(new SimpleGrantedAuthority(role.getRolename()));
}
return grantedAuthorities;
}
public Collection<String> getLoggedInUsers() {
return sessionRegistry.getAllPrincipals().stream()
.filter(u -> !sessionRegistry.getAllSessions(u, false).isEmpty())
.map(Object::toString)
.collect(Collectors.toList());
}
}
我在 AccRegistrationController 中添加了一些 println 语句到我的代码中,以找出问题出在哪里,因为在注册过程中/之后没有发生错误。我发现问题一定出在这行代码中:
Authentication authentication = authenticationManager.authenticate(token);
但我不能说什么是错的。可能有一些 authenticationManager 不正确。
无论我注意到什么,“registerAccount”方法都没有执行到最后。重定向不起作用,我被重定向到登录页面。
我希望你能帮助我找出我的错误。
解决方案
登录用户最简单的方法是调用HttpServletRequest.login(String username, String password)
方法。
在AccRegistrationController.registerAccount
中,您可以用这个替换所有最后一部分
/*UsernamePasswordAuthenticationToken token = new
UsernamePasswordAuthenticationToken(user.getEmail(), user.getPassword());
request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());
token.setDetails(new WebAuthenticationDetails(request));
Authentication authentication = authenticationManager.authenticate(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
*/
request.login(user.getEmail(), user.getPassword());
这将开始整个 Spring 身份验证流程。
推荐阅读
- winforms - 在安装 Windows 安装程序包之前检查是否安装了先决条件
- python - 如何合并(太大)数据框?
- python - 按所有类别分组,在一个函数上聚合并在 pandas 中填写结果 NA
- python - 3d 坐标 x,y,z 到 3d numpy 数组
- magento2 - Google Express - 订单发票:createchargeinvoice
- java - 为什么 Java/JVM 实现选择 HEAP 数据结构将对象存储在内存中?
- python - Flask,从 HTML 中获取价值
- php - 来自服务器端 Firebase + PHP 的电话身份验证验证
- git - 从 svn repo 签出每个版本并使用散列的提交者 ID 提交到新的 repo
- c# - .NET 序列化 getter 和 setter