Spring Security 源码分析二:Core Components 核心元素

前言

本文是对 Spring Security Core 4.0.4 Release 进行源码分析的系列文章之一;

本文非常简短,主要描述 Spring Security 的几大核心元素,以及通过官网的一个例子来描述其最核心的验证过程;

本文为作者的原创作品,转载需注明出处;

环境

使 test 通过 project reference 的方式引用 Spring Core 工程;

测试用例

这里采用官网上的一段测试程序来对 Spring Core 进行调试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import org.springframework.security.authentication.*;
import org.springframework.security.core.*;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;

public class AuthenticationExample {

private static AuthenticationManager am = new SampleAuthenticationManager();

public static void main(String[] args) throws Exception {

BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

while (true) {

System.out.println("Please enter your username:");

String name = in.readLine();

System.out.println("Please enter your password:");

String password = in.readLine();

try {

Authentication request = new UsernamePasswordAuthenticationToken(name, password);

Authentication result = am.authenticate(request);

SecurityContextHolder.getContext().setAuthentication(result);

break;
} catch (AuthenticationException e) {
System.out.println("Authentication failed: " + e.getMessage());
}
}
System.out.println("Successfully authenticated. Security context contains: "
+ SecurityContextHolder.getContext().getAuthentication());
}
}

class SampleAuthenticationManager implements AuthenticationManager {

static final List<GrantedAuthority> AUTHORITIES = new ArrayList<GrantedAuthority>();

static {
AUTHORITIES.add(new SimpleGrantedAuthority("ROLE_USER"));
}

public Authentication authenticate(Authentication auth) throws AuthenticationException {

if (auth.getName().equals(auth.getCredentials())) {

return new UsernamePasswordAuthenticationToken(auth.getName(), auth.getCredentials(), AUTHORITIES);
}
throw new BadCredentialsException("Bad Credentials");
}
}

该测试用例中,直接涵盖了 Spring Security Core 的几大核心组件,

  • SecurityContextHolder
    SecurityContextHolder 为当前线程创建了一个 ThreadLocal 用于存放当前的 SecurityContext,既是当前 Spring Security 的上下文,包含对象,参数等任何一切与 Spring Security 相关的内容;不过,SecurityContextHolder 不一定非要将 SecurityContext 放置在线程中,比如 Swing client 客户端,用户的 Security Context 并不需要放置在一个线程中在,这个时候,可以通过设置 _SecurityContextHolder.MODE_GLOBAL_ 将 SecurityContext 放置在全局的环境之下;

  • Authentication
    org.springframework.security.core.Authenticationjava.security.Principal 的继承接口,提供了 Spring Security 额外需要的用户认证相关的接口信息,比如 Credentials,Details information,is Authenticated 等等信息;

  • AuthenticationManager
    AuthenticationManager 提供了认证方法的入口,上述代码中可以清晰的看到,我们自定义实现了一个 SampleAuthenticationManager,提供对当前的用户进行认证;

  • UsernamePasswordAuthenticationToken
    可以看到,该 Token 是 Authentication 的一个实现类,表示当前用户的认证信息

  • GrantedAuthority

从上述的分析中可以看到,虽然很简单,但是恰到好处的描绘了 Spring Security Core 去验证用户的行为,很简单,就是通过 AuthenticationManager 对用户当前的 Authentication 既用户身份信息通过 authenticate 接口方法进行验证,若通过验证则返回被授权的 Authentication 对象,同时赋予其 AUTHORITIES,若认证失败,则抛出 AuthenticationException 异常;

从上述的分析中可以看到,最开始 UsernamePasswordAuthenticationToken 对象是一个未被授权的 Authentication 对象,一旦经过授权,该 UsernamePasswordAuthenticationToken 对象将会被填充其授权的信息,这里就是指 AUTHORITIES