整合JWT _ 登录信息到上下文

引入JWT依赖

<jwt.version>0.9.1</jwt.version>

<!-- JWT相关 -->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>${jwt.version}</version>
</dependency

<!-- JWT相关 -->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
</dependency>

聚合工程和common各引入一份JWT依赖

编写生成/解析token工具类

@Slf4j
public class JWTUtil {
	/** token 过期时间,7天 */
	private static final long EXPIRE = 1000 * 60 * 60 * 24 * 7;
	/** 加密秘钥 */
	private static final String SERCET = "xdclass";
	/** 令牌前缀 */
	private static final String TOKEN_PREFIX = "ovo";
	/** subject */
	private static final String SUBJECT = "xdclass";
    
	/** 生成Token */
	public static String geneJsonWebToken(LoginUser loginUser) {
		if(loginUser == null){
			throw new NullPointerException(" loginUser 对象为空");
		}
		String token = Jwts.builder().setSubject(SUBJECT)
				.claim("id", loginUser.getId())
				.claim("name", loginUser.getName())
				.claim("mail", loginUser.getMail())
				.claim("avater", loginUser.getAvater())
				.setIssuedAt(new Date())
				.setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
				.signWith(SignatureAlgorithm.HS256, SERCET).compact();
		return TOKEN_PREFIX + token;
	}
    
	/** 校验token */
	public static Claims checkJWT(String token) {
		try {
			return Jwts.parser()
					.setSigningKey(SERCET)
					.parseClaimsJws(token.replace(TOKEN_PREFIX, "")).getBody();
		} catch (Exception e) {
			log.info("token 解析失败");
			return null;
		}
	}
}

生成token时将登录用户的部分信息放入token中进行加密,
后续进行操作时可以解析token取出登录用户的信息存入线程中

在登录方法中生成token并返回

@Override
public JsonData login(UserLoginRequest loginRequest) {
	UserDO user = lambdaQuery().eq(UserDO::getMail, loginRequest.getMail()).one();
	if(user == null){
		return JsonData.buildResult(BizCodeEnum.ACCOUNT_UNREGISTER);
	}
	String pwd = SecureUtil.sha256(loginRequest.getPwd() + user.getSecret());
	if(!pwd.equals(user.getPwd())){
		return JsonData.buildResult(BizCodeEnum.ACCOUNT_PWD_ERROR);
	}
	// 登录成功,生成token, TODO 保存到redis
	LoginUser loginUser = BeanUtil.copyProperties(user, LoginUser.class);
	String token = JWTUtil.geneJsonWebToken(loginUser);
	return JsonData.buildSuccess(token, "登录成功");
}

配置登录拦截器

@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		// 取出 token
		String accessToken = request.getHeader("token");
		if (accessToken == null){
			accessToken = request.getParameter("token");
		}
		// token 为 null
		if(StrUtil.isBlank(accessToken)){
			CommonUtil.sendJsonMessage(response, JsonData.buildResult(BizCodeEnum.ACCOUNT_UNLOGIN));
		}
		// 解析 token
		Claims claims = JWTUtil.checkJWT(accessToken);
		if(claims == null){
			CommonUtil.sendJsonMessage(response, JsonData.buildResult(BizCodeEnum.ACCOUNT_UNLOGIN));
			return false;
		}
		// 取出解析token后的信息
		Long userId = Long.valueOf(claims.get("id").toString());
		String name = (String) claims.get("name");
		String mail = (String) claims.get("mail");
		String avater = (String) claims.get("avater");
		// 封装成 LoginUser 对象
		LoginUser loginUser = LoginUser.builder()
				.id(userId)
				.name(name)
				.mail(mail)
				.avater(avater)
				.build();
		// 将 loginUser 放入上下文
		BaseContext.setCurrentId(userId);
		BaseContext.setLoginUser(loginUser);
		return true;
	}
}

拦截请求, 解析token, 将解析后的用户信息存入线程中, 方便后面使用

配置登录拦截器的拦截路径

@Slf4j
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
	@Override
	public void addInterceptors(InterceptorRegistry registry){
		registry.addInterceptor(new LoginInterceptor())
				// 拦截的路径
				.addPathPatterns("/api/user/*/**","/api/address/*/**")
				// 不拦截的路径
				.excludePathPatterns("/api/user/*/send_code","/api/user/*/captcha",
						"/api/user/*/login","/api/user/*/register","/api/user/*/upload");
	}
}

请求上下文类

public class BaseContext {
	/**
	 * 用于将当前线程的 ID 设置为指定的 id 值。
	 * 它将 id 值存储在当前线程的 threadLocal 对象中,以便在其他地方可以获取到当前线程的 ID。
	 */
	public static ThreadLocal<Long> threadID = new ThreadLocal<>();
	public static void setCurrentId(Long id) {
		threadID.set(id);
	}
	public static Long getCurrentId() {
		return threadID.get();
	}
	public static void removeCurrentId() {
		threadID.remove();
	}
	/**
	 * 用于将当前线程的用户名设置为指定的 LoginUser 值。
	 * 它将 LoginUser 值存储在当前线程的 threadLoginUser 对象中,以便在其他地方可以获取到当前线程的登录信息。
	 */
	public static ThreadLocal<LoginUser> threadLoginUser = new ThreadLocal<>();
	public static void setLoginUser(LoginUser loginUser) {
		threadLoginUser.set(loginUser);
	}
	public static LoginUser getLoginUser() {
		return threadLoginUser.get();
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值