欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

token的作用和实现原理代码及验证token

程序员文章站 2022-07-02 23:30:05
...

token
在计算机身份认证中是令牌(临时)的意思,在词法分析中是标记的意思。一般作为邀请、登录系统使用。

http 请求的无状态性
JWT (jsonwebtoken)

用户登录 服务器端产生一个token (加密字符串) 发送给前端
前端将token 进行保存
前端发起数据请求的时候携带token
服务端 验证token 是否合法 如果合法继续操作 不合法终止操作
token 的使用场景 无状态请求 保持用户的登录状态 第三方登录

之所以遇到token是因为涉及到了微信第三方登录并绑定自己app端账户的手机号
app端微信授权会给后端返回小程序登录时获取的 code
后端拿到code 并用 appid + secret+code+authorization_code(授权类型)
去请求微信的接口"https://api.weixin.qq.com/sns/jscode2session"
并得到返回来的唯一的标识 openId
可将openId 跟用户的唯一标识手机号进行绑定即可

而token 是在用户每次登录时候产生的 ,用于身份验证。
具体实现代码:

public class LoginController extends BaseController {
    @Value("${weixin.shop.appid}")
    private String appid;
    @Value("${weixin.shop.secret}")
    private String secret;
    @Value("${token.name}")
    private String serviceToken;
    @Autowired
    private IUserService userService;
    @Resource
    private CacheManager cacheManager;
 // 小程序登录时获取的 code
        String jsCode = req.getCode();
        // 授权类型 authorization_code
        String grantType = "authorization_code";

        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appid + "&secret=" + secret + "&js_code=" + jsCode + "&grant_type=" + grantType;
        CloseableHttpClient client = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet(url);
        CloseableHttpResponse res = client.execute(httpGet);

        if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
            HttpEntity entity = res.getEntity();
            String result = EntityUtils.toString(entity, "UTF-8");
            JSONObject jsonObject = JSON.parseObject(result);
            Map<String, Object> map = new HashMap<String, Object>();
            String openId = jsonObject.getString("openid");
            if(openId != null && !"".equals(openId.trim())){
                QueryWrapper<SysUser> userQueryWrapper = new QueryWrapper<>();
                userQueryWrapper.eq("open_id", openId);
                SysUser user = userService.getOne(userQueryWrapper);
                if(user != null){
                    Cache cache =  cacheManager.getCache("serviceCacheToken");
                    String uuid = UUID.randomUUID().toString().replaceAll("-","");
                    cache.put(uuid, user);
                    Map<String, String> resultMap = new HashMap<>();
                    resultMap.put(serviceToken, uuid);
                    return AjaxResult.success(resultMap);
                }
                return  AjaxResult.success(1001, openId);
            }
        }
        MSG = "未获得微信授权";
        return  AjaxResult.error(MSG);
    }
  }

而token是可以有时间限制的,比如两个小时之后便会失效。
可以在缓存的配置文件中配置token的生命周期

<defaultCache
            name = "serviceCacheToken"
            eternal = "false"
            maxElementsInMemory = "10000"
            overflowToDisk = "true"
            diskPersistent = "false"
            timeToIdleSeconds = "7200"   // 这里就是token的有效时间  /秒
            timeToLiveSeconds = "7200"  // token的有效时间
            diskExpiryThreadIntervalSeconds = "120"
            memoryStoreEvictionPolicy = "LRU"/>

前端发起数据请求的时候可以在header中携带token去访问后端的接口
例如
token的作用和实现原理代码及验证token

		String token = request.getHeader(serviceToken);
        Cache cache =  cacheManager.getCache("serviceCacheToken");
        SysUser user = cache.get(token, SysUser.class);

后端可以验证token 然后进行下一步的操作
验证token具体代码:

/**
     * 验证token
     * @param joinPoint
     * @return
     * @throws Throwable
     * @author: james
     */
    @Around("validateToken()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        Object result = null;
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes)requestAttributes).getRequest();

        String token = request.getHeader(serviceToken);
        if(StringUtils.isEmpty(token)) {
            return error(ErrorEnum.TOKEN_EMPTY.code, ErrorEnum.TOKEN_EMPTY.message);
        }
        try{
            SysUser user =  cacheManager.getCache("serviceCacheToken").get(token, SysUser.class);
            if (user == null) {
                return error(ErrorEnum.TOKEN_ERROR.code, ErrorEnum.TOKEN_ERROR.message);
            }
        }catch (Exception e){
            return error(ErrorEnum.SYSTEM_ERROR.code, ErrorEnum.SYSTEM_ERROR.message);
        }

        result = joinPoint.proceed();
        return result;
    }

加油,一起进步!!!