Java 高并发情况下token 信息错乱

1.当前获取token是这么取得

		因为在高并发情况下使用getLoginUserInfo获取用户信息是会错乱的因为httpServletRequest是公共的如
		protected HttpServletRequest httpServletRequest;这种获取方式
  @PostMapping("/wxCurrentUser")
    @ApiOperation(value = "获取小程序当前用户信息")
    @EncryptionAccess
    public GatewayResp<UserInfoResp> wxCurrentUser(){
        log.info("个人页面从token中获取用户信息="+JSON.toJSONString(getLoginUserInfo()));
        return GatewayResp.ok(getLoginUserInfo());
    }
protected HttpServletRequest httpServletRequest;
  /**
     * 根据token获取登录用户信息
     */
    public UserInfoResp getLoginUserInfo() {
        String token = httpServletRequest.getHeader("token");
        if (StringUtils.isNotEmpty(token) && token.contains("|")) {
            token = token.split("\\|")[0];
        }
        String accessToken = redisTemplate.opsForValue().get(token);
        return JSON.parseObject(accessToken, UserInfoResp.class);
    }

2.解决方案

在当前接口种获取token
如:

@PostMapping("/wxCurrentUser")
    @ApiOperation(value = "获取小程序当前用户信息")
    @EncryptionAccess
    public GatewayResp<UserInfoResp> wxCurrentUser(){
        log.info("个人页面从token中获取用户信息="+JSON.toJSONString(getLoginUserInfo(HttpServletRequest request)));
        
        return GatewayResp.ok(getLoginUserInfo(httpServletRequest.getHeader("token")));
    }
/**
     * 获取登陆用户信息
     */
    public UserInfoResp getLoginUserInfo(String token) {
        String accessToken = redisTemplate.opsForValue().get(token);
        if (StringUtils.isBlank(accessToken)) {
            return getLoginUserInfo();
        }
        return JSON.parseObject(accessToken, UserInfoResp.class);
    }
	
	这样就变为单独线程获取token,能有效得阻止信息错乱

第二种方案

使用LoginUserThreadLocal 来做高并发用户存取

package com.chinaunicom.standard.product.ucenter.provider.api.intercepter;

import com.chinaunicom.standard.product.ucenter.domain.resp.UserInfoResp;

/**
 * <p>
 * 获取当前登录用户ThreadLocal
 * </p>
 *
 * @author zhaomingleiGlobalExceptionHandler
 * @since 2020-09-17
 */
public class LoginUserThreadLocal {

	// 记录保存
	private static final ThreadLocal<UserInfoResp> localPage = new ThreadLocal<>();

	/**
	 * 设定当前登录用户
	 */
	public static void set(UserInfoResp user){
		localPage.set(user);
	}

	/**
	 * 取得登录的用户
	 * @return
	 */
	public static UserInfoResp get(){
		UserInfoResp user = localPage.get();
		localPage.remove();
		return user;
	}

}

把用户信息放在LoginUserThreadLocal中

LoginUserThreadLocal.set(userInfoResp);

获取用户信息

 public UserInfoResp getLoginUserInfo() {
        String token = httpServletRequest.getHeader("token");
        /*if (StringUtils.isNotEmpty(token) && token.contains("|")) {
            token = token.split("\\|")[0];
        }
        String accessToken = redisTemplate.opsForValue().get(token);
        UserInfoResp userInfoResp = JSON.parseObject(accessToken, UserInfoResp.class);
        log.info("当前线程:{},token:{},用户信息:{}",Thread.currentThread().getId(),token,userInfoResp.getUserName());
        return userInfoResp;*/
        UserInfoResp userInfoResp = LoginUserThreadLocal.get();
        log.info("当前线程:{},token:{},用户信息:{}",Thread.currentThread().getId(),token,userInfoResp);
        return userInfoResp;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值