📜  spring security 注册后自动登录 - Java (1)

📅  最后修改于: 2023-12-03 14:47:33.906000             🧑  作者: Mango

Spring Security 注册后自动登录

简介

在使用 Spring Security 实现用户注册和登录功能时,用户注册后需要再手动进行一次登录操作。本篇文章将介绍如何实现用户注册后自动登录的功能。

实现步骤
1. 添加依赖

pom.xml 中添加 Spring Security 的依赖:

<dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-web</artifactId>
  <version>5.2.2.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-config</artifactId>
  <version>5.2.2.RELEASE</version>
</dependency>
2. 配置 Spring Security

在 Spring Security 的配置类中添加以下配置:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
  // ...

  @Autowired
  private UserDetailsService userDetailsService;

  @Autowired
  private PersistentTokenRepository tokenRepository;

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

    http
      // ...
      .formLogin()
      // ...
      .successHandler(authenticationSuccessHandler())
      // ...
      .and()
      // ...
      .rememberMe()
      .tokenRepository(tokenRepository)
      .userDetailsService(userDetailsService)
      .rememberMeCookieName("my-remember-me-cookie")
      .and()
      // ...
      .logout()
      // ...
      .and()
      // ...
      .csrf()
      .disable(); // 为了实现方便,关闭了 csrf 防护
  }

  @Bean
  protected AuthenticationSuccessHandler authenticationSuccessHandler() {
    return new SimpleUrlAuthenticationSuccessHandler() {
      @Override
      public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        super.onAuthenticationSuccess(request, response, authentication);

        // 自动登录逻辑
        if (authentication.isAuthenticated() && CookieUtils.getCookieValue(request, "remember-me") == null) {
          User user = (User) authentication.getPrincipal();
          PersistentRememberMeToken token = new PersistentRememberMeToken(
            user.getUsername(),
            getTokenSeries(),
            getTokenValue(),
            new Date()
          );
          tokenRepository.createNewToken(token);
          Cookie rememberMeCookie = new Cookie("remember-me", token.getSeries());
          rememberMeCookie.setMaxAge(60 * 60 * 24 * 30); // 一个月后失效
          rememberMeCookie.setPath("/");
          response.addCookie(rememberMeCookie);
        }
      }
    };
  }

  // ...
}

在配置中,我们主要做了以下几件事情:

  • 配置了表单登录,并指定登录成功后的处理器为 authenticationSuccessHandler()
  • 配置了 Remember-Me 功能,并指定数据访问对象 PersistentTokenRepository 和用户详细信息服务 UserDetailsService
  • 在自定义的登录成功处理器 authenticationSuccessHandler() 中,实现了自动登录的逻辑。如果用户已经通过身份验证,并且没有记住我 Cookie 的话,就生成新的记住我 Token 并写入浏览器的 Cookie 中。
3. 样例代码

在一个简单的 Spring Boot 应用中,完成用户注册和登录的样例代码如下:

@Service
public class UserServiceImpl implements UserService {
  private final UserRepository userRepository;

  public UserServiceImpl(UserRepository userRepository) {
    this.userRepository = userRepository;
  }

  @Override
  public User save(User user) {
    user.setPassword(new BCryptPasswordEncoder().encode(user.getPassword()));
    return userRepository.save(user);
  }

  @Override
  public User findByUsername(String username) {
    return userRepository.findByUsername(username);
  }
}

@Controller
public class AuthController {
  private final UserService userService;

  public AuthController(UserService userService) {
    this.userService = userService;
  }

  @GetMapping("/register")
  public String registerPage(Model model) {
    model.addAttribute("user", new User());
    return "register";
  }

  @PostMapping("/register")
  public String register(@ModelAttribute User user) {
    userService.save(user);
    return "redirect:/login";
  }

  @GetMapping("/login")
  public String loginPage() {
    return "login";
  }
}

@RestController
public class UserController {
  private final UserService userService;

  public UserController(UserService userService) {
    this.userService = userService;
  }

  @GetMapping("/user")
  public Principal user(Principal principal) {
    return principal;
  }
}

@Entity
@Table(name = "users")
public class User implements UserDetails {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

  @Column(unique = true)
  private String username;

  private String password;

  public User() {}

  // getters, setters and other UserDetails methods
}

在样例代码中,我们通过 UserService 实现了用户注册和找到用户等业务逻辑,通过 AuthController 实现了注册页面和登录页面的访问,通过 UserController 实现了用户信息的获取。具体逻辑请根据实际情况进行调整。

总结

本篇文章介绍了如何在 Spring Security 中实现用户注册后自动登录的功能。通过这个功能,可以提高用户体验,减少不必要的操作。