2017-09-14 308 views
2

在我的Spring Boot MVC应用程序中,我使用Spring Security来提供身份验证和用户注册。用户的身份验证和注册工作正常,但创建用户帐户后,我想自动登录他。在做这件事的时候,我收到了BadCredentialsException。具有相同凭证的此用户通常会使用登录表单正确登录。我感谢你的任何帮助。下面是我的代码:Spring Security - 注册用户后自动登录失效

从控制器

@RequestMapping(value = "/register", method = RequestMethod.POST) 
public String registerUser(@ModelAttribute("user") User user, BindingResult result, 
          WebRequest request, Errors errors) { 
    User registeredUser = null; 
    if (result.hasErrors() == false) { 
     registeredUser = createUserAccount(user, result); 
    } 
    if (registeredUser == null) { 
     return "/register"; 
    } 
    securityService.autologin(registeredUser.getLogin(), registeredUser.getPassword()); 

    return "/whiprounds"; 
} 

SecurityServiceImpl(方法身份验证时抛出例外)

@Service 
public class SecurityServiceImpl implements SecurityService { 
    @Autowired 
    private AuthenticationManager authenticationManager; 

    @Autowired 
    private UserDetailsService userDetailsService; 

    private static final Logger logger = LoggerFactory.getLogger(SecurityServiceImpl.class); 

    @Override 
    public String findLoggedInLogin() { 
     Object userDetails = SecurityContextHolder.getContext().getAuthentication().getDetails(); 
     if (userDetails instanceof UserDetails) { 
      return ((UserDetails) userDetails).getUsername(); 
     } 

     return null; 
    } 

    @Override 
    public void autologin(String username, String password) { 
     UserDetails userDetails = userDetailsService.loadUserByUsername(username); 
     UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(userDetails, password, userDetails.getAuthorities()); 

     authenticationManager.authenticate(usernamePasswordAuthenticationToken); 

     if (usernamePasswordAuthenticationToken.isAuthenticated()) { 
      SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken); 
      logger.debug(String.format("Auto login %s successfully!", username)); 
     } 
    } 
} 

UserServiceImpl

@Service 
public class UserServiceImpl implements UserService { 

    @Autowired 
    private UserRepository userRepository; 

    @Autowired 
    private BCryptPasswordEncoder bCryptPasswordEncoder; 

    @Autowired 
    private RoleRepository roleRepository; 

    @Override 
    public User registerNewUserAccount(User user) throws LoginExistsException { 
     if (loginExists(user.getLogin())) { 
      throw new LoginExistsException("User with this login already exists"); 
     } 
     user.setPassword(bCryptPasswordEncoder.encode(user.getPassword())); 
     user.setRoles(new HashSet<>((Collection<? extends Role>) roleRepository.findAll())); 

     return userRepository.save(user); 
    } 

    private boolean loginExists(String login) { 
     User user = userRepository.findByLogin(login); 
     if (user != null) { 
      return true; 
     } 
     return false; 
    } 
} 
方法

UserDetailsS​​erviceImpl

@Service 
public class UserDetailsServiceImpl implements UserDetailsService { 

    @Autowired 
    private UserRepository userRepository; 

    @Override 
    @Transactional(readOnly = true) 
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { 
     User user = userRepository.findByLogin(s); 

     if (user == null) { 
      throw new UsernameNotFoundException(s); 
     } 

     Set<GrantedAuthority> grantedAuthorities = new HashSet<>(); 
     for (Role role : user.getRoles()) { 
      grantedAuthorities.add(new SimpleGrantedAuthority(role.getName())); 
     } 

     return new org.springframework.security.core.userdetails.User(user.getLogin(), user.getPassword(), grantedAuthorities); 
    } 
} 

回答

1

首先,这种方法抛出,因为密码问题的一个例外(据我可以从你的代码中看到的)。您的方法registerNewUserAccount返回User对象哪些密码已被散列。然后,你在这里传递:

securityService.autologin(registeredUser.getLogin(), registeredUser.getPassword()); 

因此,原来是你传递哈希密码到authenticationManager后来。这是错误的 - 您应该将原始密码传递给它。水木清华这样的:

@RequestMapping(value = "/register", method = RequestMethod.POST) 
public String registerUser(@ModelAttribute("user") User user, BindingResult result, 
         WebRequest request, Errors errors) { 
    User registeredUser = null; 
    String originalPassword = user.getPassword(); 
    if (result.hasErrors() == false) { 
     registeredUser = createUserAccount(user, result); 
    } 
    if (registeredUser == null) { 
     return "/register"; 
    } 
    securityService.autologin(registeredUser.getLogin(), originalPassword); 

    return "/whiprounds"; 
} 

所有authenticationManager.authenticate(usernamePasswordAuthenticationToken);二 - 这种方法实际上返回充满Authentication对象(如果认证成功),你应该把这个对象为SecurityContext,而不是你已经通过了一个到`authenticationManager'。笑话是这样的:

@Override 
public void autologin(String username, String password) { 
    UserDetails userDetails = userDetailsService.loadUserByUsername(username); 
    UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(userDetails, password, userDetails.getAuthorities()); 

    Authentication auth = authenticationManager.authenticate(usernamePasswordAuthenticationToken); 

    if (auth.isAuthenticated()) { 
     SecurityContextHolder.getContext().setAuthentication(auth); 
     logger.debug(String.format("Auto login %s successfully!", username)); 
    } 
} 

希望这会有所帮助。

+0

是的,它的工作。非常感谢你的帮助:) – DoeUS