在我的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);
}
}
首先,由于密码问题,这个方法引发了一个异常(据我从代码中看到的)。你的方法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)。