当前位置: 首页 > 知识库问答 >
问题:

Spring Security-注册用户后自动登录不起作用

莫河
2023-03-14

在我的Spring Boot MVC应用程序中,我使用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;
    }
}

UserDetailsServiceImpl

@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个答案

滕学义
2023-03-14

首先,由于密码问题,这个方法引发了一个异常(据我从代码中看到的)。你的方法registernewseraccount返回User对象,该对象的密码已经被散列。然后你把它传给这里:

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

所以事实证明,您稍后会将散列密码传递给身份验证管理器。这是错误的-您应该将原始密码传递给它。像这样的Smth:

@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,而不是你已经传递给'身份验证管理器'的那个。Smth是这样的:

@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));
    }
}

希望这有帮助。

 类似资料:
  • 问题内容: 这是我目前用于注册的内容: 是否可以不要求用户在创建帐户后手动登录,而是简单地自动登录?谢谢。 编辑:我曾尝试过login()函数,但没有成功。我相信问题是未设置AUTHENTICATION_BACKENDS。 问题答案: 使用authenticate()和login()功能:

  • 问题内容: 我想要在spring成功注册后自动登录:我有一个受保护的页面,需要登录才能访问它们,我要在注册后跳过登录页面并进行自动登录,以便用户可以看到受保护的页面有我吗?我正在使用spring 3.0,spring security 3.0.2,该怎么做? 问题答案: 可以通过以下方式(半伪代码)通过spring安全性完成此操作: 更新:仅包含注册后如何创建会话

  • 我正在尝试在用户注册后自动登录。 我的用户注册方法: 我的用户实体模型: 用户注册成功并记录在数据库中。但要登录,将显示以下错误: SessionGuard中的ErrorException。php第407行:传递给illumb\Auth\SessionGuard::login()的参数1必须是illumb\Contracts\Auth\authenticable的实例,给定的App\User\u实

  • 我在通过网络浏览器(IE或Chrome)使用ADFS登录应用程序时遇到问题。我希望使用ADFS SAML自动、透明地登录用户(当前用户已登录),而无需输入这些标识符。 所以我有2台运行Windows 2016 Server的服务器:-第一个Serv1:带有Active Directory目录的域控制器-第二个Serv2:ADFS服务器(4.0),它连接到控制器Serv1 当我试图访问我的应用程序时

  • 问题内容: 我们正在Symfony 2中从头开始构建一个业务应用程序,我在用户注册流程上遇到了一些麻烦:用户创建帐户后,应该使用这些凭据自动登录。立即被迫再次提供其凭据。 任何人都对此有任何经验,或者能够为我指明正确的方向? 问题答案: Symfony 4.0 此过程尚未从symfony 3更改为4,但是这里是使用新推荐的AbstractController的示例。无论是和服务注册在父方法,所以你

  • 我使用的是AWS Cognito的JavaScript SDK(http://docs.AWS.amazon.com/Cognito/latest/developerGuide/using-amazon-cognito-user-identity-pools-javascript-examples.html)。