Spring Security -- SecurityContextHolder 详解

前言

SecurityContextHolder 按字面意思理解,就是安全上下文支持。在使用了 Spring Security 的 Spring Boot 应用中,我们在后端想要获取登录用户的信息,可以使用命令:

SecurityContextHolder.getContext().getAuthentication().getPrincipal()

源码分析

这里调用了方法.getContext(),打开 SecurityContextHolder 的源码,部分源码如下

public class SecurityContextHolder {
    public static final String MODE_THREADLOCAL = "MODE_THREADLOCAL";
    public static final String MODE_INHERITABLETHREADLOCAL = "MODE_INHERITABLETHREADLOCAL";
    public static final String MODE_GLOBAL = "MODE_GLOBAL";
    public static final String SYSTEM_PROPERTY = "spring.security.strategy";
    private static String strategyName = System.getProperty("spring.security.strategy");
    private static SecurityContextHolderStrategy strategy;
    private static int initializeCount = 0;
    
    ...

    private static void initialize() {
        if (!StringUtils.hasText(strategyName)) {
            strategyName = "MODE_THREADLOCAL";
        }

        if (strategyName.equals("MODE_THREADLOCAL")) {
            strategy = new ThreadLocalSecurityContextHolderStrategy();
    ...

    public static SecurityContext getContext() {
        return strategy.getContext();
    }
    ...

可以看到,方法.getContext()来源于 SecurityContextHolderStrategy ,再打开 SecurityContextHolderStrategy 的源码:

package org.springframework.security.core.context;

public interface SecurityContextHolderStrategy {
    void clearContext();

    SecurityContext getContext();

    void setContext(SecurityContext var1);

    SecurityContext createEmptyContext();
}

可知 SecurityContestHolderStrategy 只是一个接口,这个接口提供创建、清空、获取、设置上下文的操作。

那它有哪些实现类呢,也就是有哪些存储策略呢?按住 Ctrl + H,查看它的实现类,如下图:

可以看出,SecurityContestHolderStrategy 有三个实现类,分别是

  1. ThreadLocalSecurityContextHolderStrategy

  2. GlobalSecurityContextHolderStrategy

  3. InheritableThreadLocalSecurityContextHolderStrategy

就跟字面意思一样三种策略分别对应 threadlocal,global,InheritableThreadLocal 三种方式。

SecurityContextHolder 默认使用的是 ThreadLocalSecurityContextHolderStrategy 安全策略。

也就是说,方法.getContext()在接口SecurityContestHolderStrategy中定义,在类 ThreadLocalSecurityContextHolderStrategy 中实现的。

然后是方法.getAuthentication(), 按 Ctrl + 鼠标左键,打开源码:

public interface SecurityContext extends Serializable {
    Authentication getAuthentication();

    void setAuthentication(Authentication var1);
}

接口 SecurityContext 只有 getAuthenticationsetAuthentication 这两个方法,而这两个方法都是 Authentication 类型。

由源码可知,所谓的安全上下文,只是保存了 Authentication(认证信息),在 Spring Security 使用一个 Authentication 对象来表示这些用户信息。

打开 Authentication 的源码:

public interface Authentication extends Principal, Serializable {
    Collection<? extends GrantedAuthority> getAuthorities();

    Object getCredentials();

    Object getDetails();

    Object getPrincipal();

    boolean isAuthenticated();

    void setAuthenticated(boolean var1) throws IllegalArgumentException;
}

由源码可知,Authentication(认证信息),主要包含了以下内容

  • getAuthorities => 可用于访问受保护资源时的权限验证

  • getCredentials => 初次认证的时候,进行填充,认证成功后将被清空

  • getDetails=> 暂不清楚,猜测应该是记录哪些保护资源已经验证授权,下次不用再验证,等等。

  • Pirncipal => 类似于 UserDetails(用户信息)

  • isAuthenticated => 是否已认证成功

参考资源

https://blog.csdn.net/baidu_38225647/article/details/104396392

https://www.cnblogs.com/longfurcat/p/9417912.html

https://blog.csdn.net/chihaihai/article/details/104830066

每天学习一点点,每天进步一点点。

原文地址:https://www.cnblogs.com/youcoding/p/14571010.html