基本思路
其中网关部分不是本章讨论的范围,网关处理与后续服务的处理类似。
- 发送处理:将认证信息植入到请求信息中
- 接收处理:从请求头中获取到认证信息,并解析为用户信息,供后续业务使用。
有两个思路:
- 将认证信息放到请求头中,向下传递。这种方式适用于用户认证上下文中信息较少,且无需包含权限、角色等信息时,使用这种方式更方便。
- 将AccessToken放到请求头中,向下传递。用户认证上下文中包含大量信息,如包含功能权限、数据权限,等信息时,推荐使用这种方式。这种方式的弊端是每次接口访问可能会出现多次的缓存访问。
这种两种方式都需要在入口处通过Filter将用户信息,放到ThreadLocal中。以便在后续使用。
前置准备
我们需要先准备一些类和实体来做基本的实现支持
- 用户信息实体
- 用户ThreadLocal存储工具类
- 认证信息获取工具类
用户实体:BaseSecurityUser
@Data
public class BaseSecurityUser {
/**
* 用户ID
*/
private String userId;
/**
* 用户姓名
*/
private String name;
// ... 省略其他字段
}
SecurityContext
:用户将BaseSecurityUser
放到ThreadLocal中
,以便在后续的业务中使用
public class SecurityContext {
private SecurityContext() {
}
private static final ThreadLocal<BaseSecurityUser> CONTEXT_HOLDER = new InheritableThreadLocal<>();
public static void clear() {
CONTEXT_HOLDER.remove();
}
public static BaseSecurityUser getUser() {
return CONTEXT_HOLDER.get();
}
public static void setUser(BaseSecurityUser user) {
CONTEXT_HOLDER.remove();
CONTEXT_HOLDER.set(user);
}
}
这里使用
InheritableThreadLocal
是为了在子线程中也能获取到用户信息。ThreadLocal
相关内容不是本篇的重点,不再在此赘述。
SecurityUtils
:用于在后续的业务代码中方便的获取到用户信息
public final class SecurityUtils {
private SecurityUtils() {
}
/**
* 获取用户信息
*
* @return 用户信息
*/
public static BaseSecurityUser getUserInfo(