1. 概述

本教程,我们将重点介绍如何在Spring Security和Spring MVC中以编程方式手动认证用户,即自定义登录验证。

2. Spring Security

简单来说,Spring Security在ThreadLocal中保存有每个认证用户的信息 —— 即Authentication对象。

为了构造和设置这个Authentication对象,我们需要使用与Spring Security一样的实现方法。

为此,让我们手动触发身份认证,然后将认证结果 —— Authentication对象设置到Spring Security当前持有的SecurityContext中,以保存当前登录的用户信息:

UsernamePasswordAuthenticationToken authReq
 = new UsernamePasswordAuthenticationToken(user, pass);
Authentication auth = authManager.authenticate(authReq);
SecurityContext sc = SecurityContextHolder.getContext();
sc.setAuthentication(auth);

完成设置后,我们现在可以通过securityContext.getAuthentication().isAuthenticated()方法,判断当前用户是否完成认证了。

3. Spring MVC

默认情况下,Spring Security会添加一个SecurityContextPersistenceFilter过滤器,作用是持久化Security Context。

它转而将Security Context的持久化委托给SecurityContextRepository实例,默认实现类为 HttpSessionSecurityContextRepository,即将SecurityContext持久化到HttpSession中。

因此,为了仅在第一次登录时设置Authentication,从而使后续请求均可用,我们需要手动将包含AuthenticationSecurityContext设置到HTTP Session中:

public void login(HttpServletRequest req, String user, String pass) { 
    UsernamePasswordAuthenticationToken authReq
      = new UsernamePasswordAuthenticationToken(user, pass);
    Authentication auth = authManager.authenticate(authReq);
    
    SecurityContext sc = SecurityContextHolder.getContext();
    sc.setAuthentication(auth);
    HttpSession session = req.getSession(true);
    session.setAttribute(SPRING_SECURITY_CONTEXT_KEY, sc);
}

SPRING_SECURITY_CONTEXT_KEY是静态导入的HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY

需要说明的是,我们不能直接使用HttpSessionSecurityContextRepository,因为它是配合SecurityContextPersistenceFilter一起使用。

4. 总结

本快速入门教程中,我们介绍了如何在Spring Security context中手动设置Authentication,并以例子演示如何实现。

惯例,本教程完整源代码可从GitHub上获取。