簡體   English   中英

Spring Boot:用戶注冊后如何自動登錄?

[英]Spring Boot: How to auto login after user registration?

這是用於用戶注冊的控制器方法:

@PostMapping("register_user")
public void registerUser(@RequestParam String email, @RequestParam String password, @RequestParam String name,
                         @RequestParam String info, HttpServletResponse response) throws EmailExistsException, IOException {
    userRepository.save(new User(email, new BCryptPasswordEncoder().encode(password), name, info));
    try {
        UserDetails userDetails = customUserDetailsService.loadUserByUsername(email);
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(userDetails, password, userDetails.getAuthorities());
        authenticationManager.authenticate(usernamePasswordAuthenticationToken);
        if (usernamePasswordAuthenticationToken.isAuthenticated()) {
            SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
            log.debug(String.format("Auto login %s successfully!", email));
        }
    } catch (Exception e) {
        log.error(e.getMessage(), e);
    }
    response.sendRedirect("/");
}

這是來自 SecurityConfig 的配置方法:

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(customUserDetailsService).passwordEncoder(new BCryptPasswordEncoder());
}

在用戶注冊期間,出現“錯誤憑據”錯誤:

org.springframework.security.authentication.BadCredentialsException: Bad credentials
at org.springframework.security.authentication.dao.DaoAuthenticationProvider.additionalAuthenticationChecks(DaoAuthenticationProvider.java:98) ~[spring-security-core-4.1.3.RELEASE.jar:4.1.3.RELEASE]
at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:166) ~[spring-security-core-4.1.3.RELEASE.jar:4.1.3.RELEASE]
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174) ~[spring-security-core-4.1.3.RELEASE.jar:4.1.3.RELEASE]
at s7.controller.ActionController.registerUser(ActionController.java:45) ~[main/:na]

注冊后用戶可以登錄,沒有任何錯誤。 我究竟做錯了什么?

PS我也嘗試過像這個主題的自動登錄成功注冊后自動登錄但我有相同的BadCredentialsException。

如果我評論authenticationManager.authenticate(usernamePasswordAuthenticationToken); , 用戶將使用正確的 authentication.getPrincipal() 在沒有任何 BadCredentialsException 的情況下自動登錄。

向 registerUser 方法添加 'HttpServletRequest request' 參數。

在這一行之后: SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);

添加這行代碼: request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());

否則用戶將不會處於 Spring Security 要求的會話中。

希望這有幫助!

我能夠使用以下代碼(SpringBoot 2.0.5)解決這個問題:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
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.stereotype.Service;

@Service
public class SecurityService {

    @Autowired
    @Lazy
    AuthenticationManager authManager;

    private Logger logger = LoggerFactory.getLogger(SecurityService.class);

    public void doLogin(String username, String password) {

        if (username == null) {
            username = "";
        }

        if (password == null) {
            password = "";
        }

        username = username.trim();

        UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
                username, password);

        Authentication authentication = authManager.authenticate(authRequest);

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

}

為了讓它工作,我最難弄清楚的是 AuthenticationManager。 您必須自動裝配您在 spring 安全配置中設置的相同 AuthenticationManager ,如下所示,不要忘記在服務上自動裝配懶惰。

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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    UsuarioService usuarioService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http
                .authorizeRequests()
                .antMatchers("/registration*").permitAll()
                .anyRequest().hasAnyAuthority("MASTER")
                .and()
                .formLogin().loginPage("/login").permitAll()
                .and()
                .csrf().disable()
                .logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/login");

    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/js/**", "/css/**", "/img/**", "/files/**", "/forgot-password"");
    }

    @Autowired
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(usuarioService);
    }

    @Bean
    public AuthenticationManager authManager() throws Exception {
        return this.authenticationManager();
    }

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

最后一個問題花了我一段時間才弄明白。 如果您使用“web.ignoring()”添加注冊端點,則安全上下文將不存在,您將無法登錄用戶。 所以一定要把它添加為 .antMatchers("/registration*").permitAll()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM