菜鸟笔记
提升您的技术认知

什么是Token(令牌)

Acess Token

  • 访问资源接口(API)时所需要的资源凭证

  • 简单token 的组成: uid(用户唯一的身份标识) 、time (当前时间的时间戳) ,sign(签名,token的前几位以hash算法压缩成的一定长度的16进制字符串)

  • 特点:

    • 服务端无状态变化、可扩展性好

    • 支持移动端设备

    • 安全

    • 支持跨域程序调用

    • token 的身份验证流程

      • 客户端使用用户名和密码进行登录
      • 服务端收到请求,去验证用户名与密码
      • 验证成功后,服务端会签发一个token 并把这个token 发送给客户端
      • 客户端收到token后,会把它存储起来,比如放在cookie 里 或者 localStorage里
      • 客户端每次向服务端请求资源的时候需要带着服务端签发的token
      • 服务端收到请求后,先验证客户端请求里带着的token ,如果验证成功,就向客户端返回请求的数据
      • 优点:
        • 每一次请求都需要携带token ,需要把token 放到HTTP的Header 里
        • 基于token 的用户验证是一种服务端无状态的认证方式,服务端不用存放token数据,用解析token的计算时间换取 session的存储空间,从而减轻服务器的压力,减少频繁的查询数据库
        • token 完全由应用管理,所以它可以避开同源策略
      • Token生成示例
        使用用户唯一ID + 系统时间 + 随机数 + 过期时间得到用户信息数据,对用户信息数据进行RSA非对称加密/AES对称加密得到一个加密字符串A,将加密字符串A再次进行签名等到一个签名数据。然后将签名数据和加密字符串进行拼接,最后使用base64进行编码,得到最终的token令牌。
      	/**
       *
       * @param tokenBody 实例对象,通常为bean
       * @param minute 过期时间   单位:min
       * @param <T>
       * @return
       */
      public static <T> String createToken(T tokenBody, int minute) {
            
          long now = System.currentTimeMillis() / 1000;
          Gson gson = new Gson();
          JsonObject jsonBody = new JsonObject();
          jsonBody.addProperty("body", gson.toJson(tokenBody));
      
          String randomAlphabetic = RandomStringUtils.randomAlphabetic(3);
          JsonObject jsonHeader = new JsonObject();
          jsonHeader.addProperty("now", now);
          jsonHeader.addProperty("rand_num", randomAlphabetic);
          jsonHeader.addProperty("expire", (now + minute * 60));
      
          String token = null;
          try {
            
              byte[] encryptContent = generateEncryptBody(jsonHeader.toString(), jsonHeader.toString());
              byte[] signWithEncrypt = generateSignWithEncrypt(encryptContent);
              token = Joiner.on(".").join(new String[]{
            base64Encoder(
                      jsonHeader.toString().getBytes("utf-8")),
                      base64Encoder(encryptContent),
                      base64Encoder(signWithEncrypt)}
                      );
          } catch (Exception e) {
            
              e.printStackTrace();
          }
          return token;
      }
      

    常见的鉴权模式

    • session-Cookie
    • Token验证(JWT SSO单点登录)
    • OAuth2.0 (开放授权)

    JWT 与 Token 的区别

    • 相同:
      • 都是访问资源的令牌
      • 都可以记录用户的信息
      • 都是使服务端无状态变化
      • 都是验证成功后,客户端才能访问服务端上受保护的资源
  • 区别

    • Token: 服务端验证客户端发送过来的Token 时,还需要查询数据库获取用户信息,然后验证Token 是否有效
    • JWT: 将token 和 Payload 加密后存储于客户端,服务端只需要使用秘钥进行校验即可,不需要查询或者减少查询数据库,因为JWT自包含了用户信息和加密的数据