我正在尝试在使用 spring security 和 boot 成功注册后对用户进行身份验证。登录和注册本身工作正常,但是当我注册时,我总是被重定向到登录页面,尽管我已经关注了这个线程(成功注册后自动登录)。
大多数在线解决方案似乎以几乎相同的方式处理该问题,但没有一个对我有用。
以下是可能影响我的问题的相关类:
注册控制器:
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.servlet.ModelAndView;
import training.spring.profilemanger.exception.PasswordsNotMatchingException;
import training.spring.profilemanger.exception.UserEmailExistsException;
import training.spring.profilemanger.model.User;
import training.spring.profilemanger.model.UserLogin;
import training.spring.profilemanger.service.UserService;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
@Controller
public class IdentificationController {
private UserService userService;
protected AuthenticationManager authenticationManager;
public IdentificationController(UserService userService, AuthenticationManager authenticationManager) {
this.userService = userService;
this.authenticationManager = authenticationManager;
}
private static final String VIEW_PATH = "identification/";
@GetMapping({"/login", "/logout"})
public ModelAndView loginForm(ModelAndView modelAndView) {
modelAndView.addObject("userLogin", new UserLogin());
modelAndView.setViewName(VIEW_PATH + "login");
return modelAndView;
}
@GetMapping("/signup")
public ModelAndView signupForm(ModelAndView modelAndView) {
modelAndView.addObject("user", new User());
modelAndView.setViewName(VIEW_PATH + "signup");
return modelAndView;
}
@PostMapping("/signup")
public ModelAndView signupSubmit(ModelAndView modelAndView, @ModelAttribute @Valid User user,
BindingResult bindingResult, @ModelAttribute("passwordConfirmation") String passwordConfirmation,
HttpServletRequest request) {
if (bindingResult.hasErrors()) {
modelAndView.setViewName(VIEW_PATH + "signup");
} else {
try {
userService.validateAllFields(user, passwordConfirmation);
userService.save(user);
authenticateUser(user, request);
modelAndView.addObject("users", userService.findAll());
modelAndView.setViewName("redirect:/users");
} catch (PasswordsNotMatchingException e) {
bindingResult.rejectValue("password", "error.user", "passwords are not matching");
modelAndView.setViewName(VIEW_PATH + "signup");
} catch (UserEmailExistsException e) {
bindingResult.rejectValue("email", "error.user", "email already in use");
modelAndView.setViewName(VIEW_PATH + "signup");
}
}
return modelAndView;
}
private void authenticateUser(User user, HttpServletRequest request) {
UsernamePasswordAuthenticationToken token =
new UsernamePasswordAuthenticationToken(user.getEmail(), user.getPassword());
// generate session if one doesn't exist
request.getSession();
token.setDetails(new WebAuthenticationDetails(request));
Authentication authenticatedUser = authenticationManager.authenticate(token);
SecurityContextHolder.getContext().setAuthentication(authenticatedUser);
request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());
}
}
网络安全配置
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import training.spring.profilemanger.service.UserService;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private PasswordEncoder passwordEncoder;
private UserDetailsService userService;
public WebSecurityConfig(PasswordEncoder passwordEncoder, UserService userService) {
this.passwordEncoder = passwordEncoder;
this.userService = userService;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/login", "/signup").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) {
auth
.authenticationProvider(authProvider());
}
@Bean
public DaoAuthenticationProvider authProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userService);
authProvider.setPasswordEncoder(passwordEncoder);
return authProvider;
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
WebMvc 配置:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
public class WebMvcConfig {
@Bean
public PasswordEncoder passwordEncoder() {
PasswordEncoder encoder = new BCryptPasswordEncoder();
return encoder;
}
}
用户服务:
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import training.spring.profilemanger.exception.PasswordsNotMatchingException;
import training.spring.profilemanger.exception.UserEmailExistsException;
import training.spring.profilemanger.model.MyUserDetails;
import training.spring.profilemanger.model.User;
import training.spring.profilemanger.repository.UserRepository;
@Service
public class UserService implements UserDetailsService {
private UserRepository userRepository;
private PasswordEncoder passwordEncoder;
public UserService(UserRepository userRepository, PasswordEncoder passwordEncoder) {
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
}
public void validateAllFields(User user, String passwordConfirmation) throws PasswordsNotMatchingException, UserEmailExistsException {
user = trimWhiteSpaces(user);
checkPasswordsMatching(user.getPassword(), passwordConfirmation);
if (userRepository.findByEmail(user.getEmail()) != null) {
throw new UserEmailExistsException();
}
}
public User save(User user) {
user.setPassword(passwordEncoder.encode(user.getPassword()));
return userRepository.save(user);
}
private User trimWhiteSpaces(User user) {
user.setFirstName(user.getFirstName().trim());
user.setLastName(user.getLastName().trim());
user.setEmail(user.getEmail().trim());
return user;
}
public Iterable<User> findAll() {
return userRepository.findAll();
}
private void checkPasswordsMatching(String password, String passwordConfirmation) throws PasswordsNotMatchingException {
if (passwordConfirmation == null || !passwordConfirmation.equals(password)) {
throw new PasswordsNotMatchingException();
}
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByEmail(username);
if (user != null) {
return new MyUserDetails(user);
} else {
throw new UsernameNotFoundException(username + " doesn't exist");
}
}
}
注册.html:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>User Form</title>
</head>
<body>
<h1>User Sign-up Form:</h1>
<form action="#" th:action="@{/signup}" th:object="${user}" method="post">
<input type="hidden" th:field="*{id}"/>
<table>
<tr>
<td>First name</td>
<td>:<input type="text" th:field="*{firstName}"/></td>
<td><label th:if="${#fields.hasErrors('firstName')}" th:errors="*{firstName}" style="color: red"/></td>
</tr>
<tr>
<td>Last name</td>
<td>:<input type="text" th:field="*{lastName}"/></td>
<td><label th:if="${#fields.hasErrors('lastName')}" th:errors="*{lastName}" style="color: red"/></td>
</tr>
<tr>
<td>Email</td>
<td>:<input type="email" th:field="*{email}"/></td>
<td><label th:if="${#fields.hasErrors('email')}" th:errors="*{email}" style="color: red"/></td>
</tr>
<tr>
<td>Password</td>
<td>:<input type="password" th:field="*{password}"/></td>
<td><label th:if="${#fields.hasErrors('password')}" th:errors="*{password}" style="color: red"/></td>
</tr>
<tr>
<td>Password Confirmation</td>
<td>:<input type="password" name="passwordConfirmation"/></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="Submit"/><input type="reset" value="Reset"/></td>
</tr>
</table>
</form>
</body>
</html>
如果您认为我遗漏了什么,请随时要求我提供。
祝你有美好的一天。