有了 Token 令牌后,在接口请求过程中携带令牌即代表当前用户已经登录了。

而很多时候我们需要获取令牌中的用户ID,例如在更新用户信息的场景,我们一般不会像 /user/{id} 这样直接将用户ID传到接口中,而是通过请求头中的 Token 来获取当前用户。

ThreadLocal

Python Flask 中有一个 flask.g 可以保存当前请求中的全局变量,例如 g.user 即可获取到当前用户。

如果 SpringBoot 也可以这样那就非常方便了。ThreadLocal 在多线程操作的时候,可以获取当前线程内存中的变量,从而规避线程安全问题。

ThreadLocal 可以通过 getset 方法得到当前线程对应的值。

下面的例子是使用 ThreadLocal 实现 LocalUser:

public class LocalUser {
	private static final ThreadLocal<User> local = new ThreadLocal<>();

	/**
	 * 获得登录用户
	 */
	public static User getLocalUser() {
		return LocalUser.local.get();
	}

	/**
	 * 设置登录用户
	 */
	public static void setLocalUser(User user) {
		LocalUser.local.set(user);
	}

	/**
	 * 清理当前用户
	 */
	public static void clearLocalUser() {
		LocalUser.local.remove();
	}
}

使用

视图层中直接通过 getLocalUser 即可获取当前用户

User localUser = LocalUser.getLocalUser();

在令牌成功时,则设置当前的登录用户

/**
 * 验证用户
 */
private static void verifyUser(String userId) {
	User user = JwtUtil.userService.getById(userId);
	if (user == null) {
		throw new NotFoundException();
	}
	LocalUser.setLocalUser(user);
}

标题:Spring Boot构建Web API Wheel(六)—— LocalUser获取当前用户
作者:Jeffrey