zoukankan      html  css  js  c++  java
  • JWT

    JWT(JSON Web Token)究竟是什么呢?它有什么用?

    权威定义:

    JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is used as the payload of a JSON Web Signature (JWS) structure or as the plaintext of a JSON Web Encryption (JWE) structure, enabling the claims to be digitally signed or integrity protected with a Message Authentication Code (MAC) and/or encrypted.

    简单地说,JWT是一个字符串,我们在发起网络请求时,将其放在header或者url中,这样可以保证传递的数据被篡改时能被我们发现,保证安全性。

    示例xxxxx.yyyyy.zzzzz即为JWT:

    http://www.example.com/private/?token=xxxxx.yyyyy.zzzzz
    小伙伴应该注意到了,JWT由3部分组成,使用两个点区分。如下:
    header.payload.signature
    1)header

    header所表示的JSON对象通常由2个部分组成:token的类型,即”JWT”; token所采用的hash算法,例如HMAC SHA256或者RSA。

    {
       "alg": "HS256",
       "typ": "JWT"
    }
    然后,这个JSON对象采用Base64Url编码变成字符串,作为JWT的第一部分。
    var header = {
        alg: 'HS256',
        typ: 'JWT'
    };
    
    // 将JSON对象使用base64编码为字符串
    var encoded_header = Buffer.from(JSON.stringify(header)).toString('base64');
    console.log(encoded_header); // 打印: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
    
    // 将base64编码的字符串解析为JSON对象
    var decoded_header = JSON.parse(Buffer.from(encoded_header, 'base64').toString());
    console.log(decoded_header); // 打印: { alg: 'HS256', typ: 'JWT' }
    可知,header只是进行了编码,而非加密,其过程是可逆的。

    2)Payload

    payload为JWT的第二部分,其JSON对象包含一系列键值对(key/value)。其中,有些预定义键有特殊含义,比如iat、exp等,iat表示JWT生成的实际,而exp代表JWT过期的时间。开发者可以使用其他非预定义的键用于传输数据。

    {
       "exp": "2100-01-01",
       "message": "Hello, Fundebug!"
    }

    然后,这个JSON对象采用Base64Url编码变成字符串,作为JWT的第二部分。

    var payload = {
        exp: '2100-01-01',
        message: 'Hello, Fundebug!'
    }
    
    // 将JSON对象使用base64编码为字符串
    var encoded_payload = Buffer.from(JSON.stringify(payload)).toString('base64');
    console.log(encoded_payload); // 打印: eyJleHAiOiIyMTAwLTAxLTAxIiwibWVzc2FnZSI6IkhlbGxvLCBGdW5kZWJ1ZyEifQ==
    
    // 将base64编码的字符串解析为JSON对象
    var decoded_payload = JSON.parse(Buffer.from(encoded_payload, 'base64').toString());
    console.log(decoded_payload); // 打印: { exp: '2100-01-01', message: 'Hello, Fundebug!' }

    **特别注意**,payload只是进行了编码,而非加密,其过程是可逆的。因此,JWT绝不是用来进行加密通信的。

    3)Signature

    signatrue,即签名,是JWT的第三部分。它由编码的header和payload,使用用户指定的密钥secret,采用header中指定的哈希算法生成。Node.js自带的[Crypto](https://nodejs.org/api/crypto.html)可以来演示signatrue是如何生成的:

    var header = {
        alg: 'HS256',
        typ: 'JWT'
    };
    
    // 使用base64编码header
    var encoded_header = Buffer.from(JSON.stringify(header)).toString('base64');
    
    
    var payload = {
        exp: '2100-01-01',
        message: 'Hello, Fundebug!'
    }
    
    // 使用base64编码pyload
    var encoded_payload = Buffer.from(JSON.stringify(payload)).toString('base64');
    
    
    const crypto = require('crypto');
    var secret = '$T697UaW6QTWsw}rrt%*P6)ia';
    
    // 生成签名signature
    var signature = crypto.createHmac('sha256', secret).update(encoded_header + '.' + encoded_payload).digest('base64');
    console.log(signature); // 打印: JiOyrHVgyTTSts6mYQpChRHO7J2/hNU4dOYkgeLthKE=

    signature是根据payload生成的,两者是一一对应的,这样可以保证payload的数据不被篡改,除非密钥secret泄漏。 最终生成的JWT为:

    var token = `${encoded_header}.${encoded_payload}.${signature}`;
    console.log(token) // 打印: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOiIyMTAwLTAxLTAxIiwibWVzc2FnZSI6IkhlbGxvLCBGdW5kZWJ1ZyEifQ==.JiOyrHVgyTTSts6mYQpChRHO7J2/hNU4dOYkgeLthKE=



    当收到JWT时,可以采用同样的算法和密钥生成签名signature,如果一致,说明数据没有被篡改。

    很重要一点在于,JWT是用于验证而非加密,任何人即使没有密钥secret,header与payload中的数据都是可以获取的。












    1

  • 相关阅读:
    史记 · 码农列传
    死侍在新片中,扮演了一个 AI 驱动的 NPC
    什么是高中物理?一篇长长长长文告诉你!
    你管这玩意叫网络?
    你管这破玩意叫计算机?
    try-catch-finally中的4个巨坑,老程序员也搞不定!
    未来几年,软件测试九大新兴趋势
    代码中大量的if/else,你有什么优化方案?
    PHP部署服务端常见问题整理
    PHP服务端环境搭建
  • 原文地址:https://www.cnblogs.com/xc-xinxue/p/12511679.html
Copyright © 2011-2022 走看看