什麼是 JSON Web Token (JWT)

將一組 JSON 資料編碼成一個 JSON Web Token (JWT) 字串,並使用密碼或公私金鑰對其進行簽名,以確保資料在傳輸過程中不被竄改。

JWT 由三部分組成,分別是 Header、Payload 和 Signature,這三部分都是用 Base64 編碼,之間使用點號 . 進行分隔。

  • HEADER(標頭):包含了 JWT 的類型和使用的加密演算法。
  • PAYLOAD(負載):包含了 JWT 的實際資料內容,也就是一組 JSON 資料。
  • VERIFY SIGNATURE(驗證簽名):簽名,用於驗證 JWT 是否為真實的。

Jwt

簽名是由 Header 和 Payload 使用 Base64 編碼後的字串,再加上一個密碼(使用指定的加密演算法進行加密)而成。 也就是:

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

手刻 JWT

    var header = new
    {
        alg = "HS256",
        typ = "JWT"
    };
    var payload = new
    {
        sub = "1234567890",
        name = "John Doe",
        iat = "1516239022"
    };
    var key = "pQeP5X9wejpFfQGgSjyWB8iFdLDGHEV8";

    byte[] headerByte = Encoding.Default.GetBytes(JsonConvert.SerializeObject(header));
    byte[] payloadByte = Encoding.Default.GetBytes(JsonConvert.SerializeObject(payload));

    string headerBase64 = Convert.ToBase64String(headerByte).TrimEnd('=');
    string payloadBase64 = Convert.ToBase64String(payloadByte).TrimEnd('=');
    var signatureByte = TSecurity.HMACSHA256($"{headerBase64}.{payloadBase64}", key);
    string signatureBase64 = Convert.ToBase64String(signatureByte).TrimEnd('=');

    string tokenString = $"{headerBase64}.{payloadBase64}.{signatureBase64}";
    public static byte[] HMACSHA256(this string value, string key)
    {
        byte[] messageBytes = Encoding.Default.GetBytes(value);
        byte[] keyByte = Encoding.Default.GetBytes(key);
        using (var hmacSHA256 = new HMACSHA256(keyByte))
        {
            byte[] hashMessage = hmacSHA256.ComputeHash(messageBytes);
            return hashMessage;
        }
    }

使用現有套件建立 JWT

Nuget安裝套件:

  • System.IdentityModel.Tokens.Jwt;
  • Microsoft.IdentityModel.Tokens;
    var key = "pQeP5X9wejpFfQGgSjyWB8iFdLDGHEV8";
    var securityKey = new SymmetricSecurityKey(Encoding.Default.GetBytes(key));
    var creds = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);

    var header = new JwtHeader(creds);

    var payload = new JwtPayload
    {
        { "sub", "1234567890" },
        { "name", "John Doe" },
        { "iat", "1516239022" }
    };

    var token = new JwtSecurityToken(header, payload);
    var handler = new JwtSecurityTokenHandler();
    string tokenString = handler.WriteToken(token);

參考資料