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

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_第1张图片

		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;
    }

加油,一起进步!!!

你可能感兴趣的:(Spring,boot)