在Spring Boot中成功注册后如何自动登录?

时间:2018-11-14 07:45:20

标签: spring-mvc spring-boot spring-security spring-data-jpa spring-data

是的,我知道这个问题已经问过了。但是关于这个问题,我也有一个不同的问题。 SecurityServiceImpl类中AuthenticationManager的authenticationManager对象,该对象未验证导致我在此时停留的细节。

我试图在每个步骤之后给出消息,通过它们可以跟踪特定代码是否起作用,并且在SecurityServiceImpl类中发现在此代码之后它不起作用

authenticationManager.authenticate(usernamePasswordAuthenticationToken);

我不知道这仅仅是我的理解。帮助我解决这个问题,如果您有更好的代码段可以解决此特定问题,请提供我的帮助。

安全配置

package com.demo.practice.configuration;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
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.bcrypt.BCryptPasswordEncoder;

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    Logger logger = LoggerFactory.getLogger(SecurityConfiguration.class);

    @Autowired
    private UserDetailsService userDetailsService;

      protected void configure(HttpSecurity http) throws Exception {
           http.authorizeRequests()
            .antMatchers("/","/register","/login").permitAll()
            .antMatchers("/student/**").hasAuthority("STUDENT")
            .antMatchers("/admin/**").hasAuthority("ADMIN")
            .anyRequest().authenticated()
            .and()
            .formLogin().loginPage("/login")
            .defaultSuccessUrl("/dashboard");
           http.csrf().disable();
        }



    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

        @Bean
        public BCryptPasswordEncoder bCryptPasswordEncoder() {
            return new BCryptPasswordEncoder();
        }
}

UserServiceImpl

package com.demo.practice.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import com.demo.practice.model.Credentials;
import com.demo.practice.model.Role;
import com.demo.practice.model.User;
import com.demo.practice.repository.UserRepository;

@Service
public class UserServiceImpl implements UserServiceInterface {

    @Autowired
    private BCryptPasswordEncoder encoder;
    @Autowired
    UserRepository userRepo;

    @Override
    public void saveUser(User user,Credentials credential) {
        user.setCredential(credential);
        user.getCredential().setUsername(user.getEmail());
        user.getCredential().setRoles(Role.STUDENT);
        user.getCredential().setPassword(encoder.encode(user.getCredential().getPassword()));
        userRepo.save(user);
    }

    @Override
    public User findUserByEmail(String name) {
        User user=userRepo.findUserByEmail(name);
        return user;
    }

}

UserDetailsS​​erviceImpl

package com.demo.practice.service;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.demo.practice.model.Credentials;
import com.demo.practice.repository.CredentialRepository;

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    CredentialRepository credRepo;

    @Override
    @Transactional(readOnly = true)
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Credentials credential =credRepo.findByUsername(username);
        List<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>();
        grantedAuthorities.add(new SimpleGrantedAuthority(credential.getRoles().toString()));
         return new org.springframework.security.core.userdetails.User(credential.getUsername(), credential.getPassword(), grantedAuthorities);
    }

}

SecurityServiceImpl

package com.demo.practice.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;

@Service
public class SecurityServiceImpl implements SecurityServiceInterface {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private UserDetailsService userDetailsService;

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

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

        return null;
    }

    @Override
    public void autologin(String username, String password) {
       System.out.println("in autologin "+username);
        UserDetails userDetails = userDetailsService.loadUserByUsername(username);
           System.out.println("in autologin at userdetails"+userDetails);
          logger.info("after userdetails "+userDetails);
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(userDetails.getUsername(), userDetails.getPassword(),userDetails.getAuthorities());
        logger.info("in autologin after usernamepasswordauthentication! ", usernamePasswordAuthenticationToken);
         authenticationManager.authenticate(usernamePasswordAuthenticationToken);
         logger.info("after authentication manager ", usernamePasswordAuthenticationToken);
          if (usernamePasswordAuthenticationToken.isAuthenticated()) {
            SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
            logger.debug(String.format("Auto login %s successfully!", username));
        }
        else System.out.println("auto login failed");
    }


}

1 个答案:

答案 0 :(得分:0)

您缺少一件事,如果要基于身份验证会话,则需要将WebAuthenticationDetails添加到令牌中,例如:

UsernamePasswordAuthenticationToken token =
                    new UsernamePasswordAuthenticationToken(principalUser, null, List.of(new SimpleGrantedAuthority(principalUser.getRole())));

token.setDetails(new WebAuthenticationDetails(request));
SecurityContextHolder.getContext().setAuthentication(token);

文档中的WebAuthenticationDetailsRecords the remote address and will also set the session Id if a session already exists (it won't create one).

有关登录/注销过程的更多信息,请查看: https://github.com/pezetem/spring-security-angular-skeleton/blob/master/src/main/java/com/pezetem/blog/code/spring_security_custom_authorizers/security/SecurityController.java

更新:

好的,可能还有另一个原因对您不起作用。 Spring Security将默认前缀添加到角色。它等于ROLE_。这意味着,当您为.hasAuthority("STUDENT")配置的终结点角色必须等于ROLE_STUDENT时,请看一下创建用户的行,并为Role.STUDENT和角色分配角色值应为ROLE_STUDENT而不是STUDENT