zoukankan      html  css  js  c++  java
  • JWT库

    JWT的定义及其组成

    转自 https://www.jianshu.com/p/168d34aab2e3

    JWT(JSON Web Token)是一个非常轻巧的规范。这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息。

    一个JWT实际上就是一个字符串,它由三部分组成,头部、载荷与签名。

    载荷(Payload)

    我们先将用户认证的操作描述成一个JSON对象。其中添加了一些其他的信息,帮助今后收到这个JWT的服务器理解这个JWT。

    {
        "sub": "1",
        "iss": "http://localhost:8000/auth/login",
        "iat": 1451888119,
        "exp": 1454516119,
        "nbf": 1451888119,
        "jti": "37c107e4609ddbcc9c096ea5ee76c667"
    }
    

    这里面的前6个字段都是由JWT的标准所定义的。

    sub: 该JWT所面向的用户
    iss: 该JWT的签发者
    iat(issued at): 在什么时候签发的token
    exp(expires): token什么时候过期
    nbf(not before):token在此时间之前不能被接收处理
    jti:JWT ID为web token提供唯一标识
    

    这些定义都可以在标准中找到。

    将上面的JSON对象进行base64编码可以得到下面的字符串:

    eyJzdWIiOiIxIiwiaXNzIjoiaHR0cDpcL1wvbG9jYWx
    ob3N0OjgwMDFcL2F1dGhcL2xvZ2luIiwiaWF0IjoxNDUxODg4MTE5LCJleHAiOjE0NTQ1MTYxMTksIm5iZiI6MTQ1MTg4OD
    ExOSwianRpIjoiMzdjMTA3ZTQ2MDlkZGJjYzljMDk2ZWE1ZWU3NmM2NjcifQ
    

    这个字符串我们将它称作JWT的Payload(载荷)。

    如果你使用Node.js,可以用Node.js的包base64url来得到这个字符串:

    
    var base64url = require('base64url')
    var header = {
        "from_user": "B",
        "target_user": "A"
    }
    
    console.log(base64url(JSON.stringify(header)))
    
    

    注:Base64是一种编码,也就是说,它是可以被翻译回原来的样子来的。它并不是一种加密过程。
    头部(Header)

    JWT还需要一个头部,头部用于描述关于该JWT的最基本的信息,例如其类型以及签名所用的算法等。这也可以被表示成一个JSON对象:

    {
      "typ": "JWT",
      "alg": "HS256"
    }
    

    在这里,我们说明了这是一个JWT,并且我们所用的签名算法(后面会提到)是HS256算法。

    对它也要进行Base64编码,之后的字符串就成了JWT的Header(头部):

    eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
    

    签名(签名)

    将上面的两个编码后的字符串都用句号.连接在一起(头部在前),就形成了:

    eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIiwiaXNzIjoiaHR0cDpcL1wvbG9jYWx
    ob3N0OjgwMDFcL2F1dGhcL2xvZ2luIiwiaWF0IjoxNDUxODg4MTE5LCJleHAiOjE0NTQ1MTYxMTksIm5iZiI6MTQ1MTg4OD
    ExOSwianRpIjoiMzdjMTA3ZTQ2MDlkZGJjYzljMDk2ZWE1ZWU3NmM2NjcifQ
    

    最后,我们将上面拼接完的字符串用HS256算法进行加密。在加密的时候,我们还需要提供一个密钥(secret):

    HMACSHA256(
        base64UrlEncode(header) + "." +
        base64UrlEncode(payload),
        secret
    )
    

    这样就可以得到我们加密后的内容:

    wyoQ95RjAyQ2FF3aj8EvCSaUmeP0KUqcCJDENNfnaT4
    

    这一部分又叫做签名。

    最后将这一部分签名也拼接在被签名的字符串后面,我们就得到了完整的JWT:

    
    eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIiwiaXNzIjoiaHR0cDpcL1wvbG9jYWx
    ob3N0OjgwMDFcL2F1dGhcL2xvZ2luIiwiaWF0IjoxNDUxODg4MTE5LCJleHAiOjE0NTQ1MTYxMTksIm5iZiI6MTQ1MTg4OD
    ExOSwianRpIjoiMzdjMTA3ZTQ2MDlkZGJjYzljMDk2ZWE1ZWU3NmM2NjcifQ.wyoQ95RjAyQ2FF3aj8EvCSaUmeP0KUqcCJDENNfnaT4

    JWT C/C++ 语言库

    https://jwt.io/ 在这个网页中列举了各种主流语言中JWT的实现。

    https://github.com/benmcollins/libjwt 这个C语言库的star较多,时间较长,所以应该比较稳定。根据README中所说,可以在Ubuntu中直接安装。下段要介绍的就是这个库。

    https://github.com/arun11299/cpp-jwt 这个库比较新,A C++14 library for JWT。Tested with clang-5.0 and g++-6.4.  VS2017 is also supported.
    因为项目不支持C++14,所以没有使用这个库,但是,看起来很有前途的样子。

    JWT C Library

     一、编译(VC++)

      1、下载源码。
      2、下载并编译依赖库:https://github.com/akheron/jansson
        json库不依赖于其他库,使用cmake直接生成VS工程,然后编译就OK。
      3、下载并编译openssl库。
      4、因为对cmake不熟,所以直接将libjwt中的文件添加到新建的VS工程中,在VS中配置好json库和openssl库。
      5、jansson,openssl都可以编译为静态库,所以libjwt也可以编译为静态库。
      6、头文件只有一个jwt.h

    二、接口说明

      1、接口说明在头文件中
      2、例子:

    #include "jwt.h"
    
    int main()
    {
        const char *json = "{"id":"FVvGYTr3FhiURCFebsBOpBqTbzHdX/DvImiA2yheXr8=","
            ""iss":"localhost"}";
    
        // jwt 指针
        jwt_t *jwt = NULL;
    
        // 密钥
        const char key[] = "My Passphrase";
    
        // 生成jwt对象
        int ret = jwt_new(&jwt);
        assert(ret == 0);
        assert(jwt != NULL);
        printf("空的jwt对象
    %s
    ", jwt_dump_str(jwt, 1));
    
        // 添加字符串内容
        ret = jwt_add_grant(jwt, "iss", "files.cyphre.com");
        assert(ret == 0);
        printf("添加字符串内容
    %s
    ", jwt_dump_str(jwt, 1));
    
        // 添加整数内容
        ret = jwt_add_grant_int(jwt, "iat", (long)time(NULL));
        assert(ret == 0);
        printf("添加整数内容
    %s
    ", jwt_dump_str(jwt, 1));
    
        // 添加json内容
        // 上述iat,iss会被添加到json中
        // 上述iss会被json中的iss覆盖
        ret = jwt_add_grants_json(jwt, json);
        assert(ret == 0);
        printf("添加json内容
    %s
    ", jwt_dump_str(jwt, 1));
    
        // 设置算法和密钥
        // 会自动生成header部分
        ret = jwt_set_alg(jwt, JWT_ALG_HS256, (unsigned char *)key,    strlen(key));
        assert(ret == 0);
        printf("设置算法和密钥
    %s
    ", jwt_dump_str(jwt, 1));
        
        // 输出最终的jwt token
        char *jwt_str = jwt_encode_str(jwt);
        printf("输出最终的jwt
    %s
    ", jwt_str);
    
        // 用来存放decode后的jwt对象
        jwt_t *jwt2 = NULL;
    
        // decode
        ret = jwt_decode(&jwt2, jwt_str, (const char unsigned *)key, strlen(key));
        assert(ret == 0);
    
        // decode后的json内容
        printf("
    Decode后的json内容
    %s
    ", jwt_dump_str(jwt2, 1));
    
        jwt_free(jwt);
        jwt_free(jwt2);
    
        return 0;
    }

      输出如下:

    空的jwt对象
    {
        "alg": "none"
    }
    .
    {}
    
    添加字符串内容
    {
        "alg": "none"
    }
    .
    {
        "iss": "files.cyphre.com"
    }
    
    添加整数内容
    {
        "alg": "none"
    }
    .
    {
        "iat": 1526283284,
        "iss": "files.cyphre.com"
    }
    
    添加json内容
    {
        "alg": "none"
    }
    .
    {
        "iat": 1526283284,
        "id": "FVvGYTr3FhiURCFebsBOpBqTbzHdX/DvImiA2yheXr8=",
        "iss": "localhost"
    }
    
    设置算法和密钥
    {
        "typ": "JWT",
        "alg": "HS256"
    }
    .
    {
        "iat": 1526283284,
        "id": "FVvGYTr3FhiURCFebsBOpBqTbzHdX/DvImiA2yheXr8=",
        "iss": "localhost"
    }
    
    输出最终的jwt
    eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1MjYyODMyODQsImlkIjoiRlZ2R1lUcjN
    GaGlVUkNGZWJzQk9wQnFUYnpIZFgvRHZJbWlBMnloZVhyOD0iLCJpc3MiOiJsb2NhbGhvc3QifQ.aeBf
    BIgoqWA8Kcz6wwrHE-3HIvSfix8K3cZaS98O5zU
    
    Decode后的json内容
    {
        "typ": "JWT",
        "alg": "HS256"
    }
    .
    {
        "iat": 1526283284,
        "id": "FVvGYTr3FhiURCFebsBOpBqTbzHdX/DvImiA2yheXr8=",
        "iss": "localhost"
    }
  • 相关阅读:
    【带着canvas去流浪(5)】绘制K线图
    【带着canvas去流浪(4)】绘制散点图
    【带着canvas去流浪】 (3)绘制饼图
    Mybatis缓存(1)--------系统缓存及简单配置介绍
    this引用逃逸
    MySQL优化(1)--------常用的优化步骤
    Java的内存模型
    Java Generator
    深入理解Java重载与重写
    对象的自我救赎
  • 原文地址:https://www.cnblogs.com/kohlrabi/p/9035248.html
Copyright © 2011-2022 走看看