URL 编码后,数字 1 随机附加到我的 JWT 密码的末尾

Posted

技术标签:

【中文标题】URL 编码后,数字 1 随机附加到我的 JWT 密码的末尾【英文标题】:Number 1 is randomly appended to the end of my JWT secret after URL encoding 【发布时间】:2018-08-17 03:39:25 【问题描述】:

我已经在每个角落和缝隙中寻找解决问题的方法,但我似乎找不到。

我有一个利用方法创建 JSON Web 令牌的类。我创建的 Web 令牌需要与以下内容匹配(请注意,我的密钥最右侧没有数字 1):

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBrZXkiOiIxMjMtNDU2LTc4OS0wIiwicmVzb3VyY2UiOiJnZXRfZ2VvY29kZSJ9.xGLb92d6yVLqLf5TnrahMCxm-OGTHmXiXLvnRUqLWYM

我生成的令牌与上面的令牌匹配,除了数字 1 随机附加在令牌的最右端:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBrZXkiOiIxMjMtNDU2LTc4OS0wIiwicmVzb3VyY2UiOiJnZXRfZ2VvY29kZSJ9.xGLb92d6yVLqLf5TnrahMCxm-OGTHmXiXLvnRUqLWYM1

如您所见,这是 JWT 中保存秘密的部分。让我演示一下我是如何生成和加密令牌的,以便您帮助诊断问题。我将向您展示整个课程,然后引导您完成这些方法。

这是整个班级:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using System.Security.Cryptography;

namespace Project.JWT

    public class Token
    

        public string CreateToken(string resource, string appkey, string secret, string algorithm)
        
            if (algorithm != "HS256")
                return "Algorithm not supported";

            JwtPayload payload = new JwtPayload
            
                appkey = appkey,
                resource = resource
            ;

            return EncodeToken(payload, secret);

        

        public static string EncodeToken(JwtPayload jwtPayload, string secret)
        
            const string algorithm = "HS256";

            var header = new Header
            
                typ = "JWT",
                alg = algorithm
            ;

            var jwt = Base64Encode(JsonConvert.SerializeObject(header)) + "." + Base64Encode(JsonConvert.SerializeObject(jwtPayload));

            jwt += "." + Sign(jwt, secret);

            return jwt;
        


        public static string Base64Encode(dynamic obj)
        
            Type strType = obj.GetType();

            var base64EncodedValue = Convert.ToBase64String(strType.Name.ToLower() == "string" ? Encoding.UTF8.GetBytes(obj) : obj);
            return base64EncodedValue;
        


        private static string Sign(string str, string key)
        


            byte[] signature;

            using (var crypto = new HMACSHA256(Encoding.UTF8.GetBytes(key)))
            
                signature = crypto.ComputeHash(Encoding.UTF8.GetBytes(str));
            

            return System.Web.HttpServerUtility.UrlTokenEncode(signature);

        

    


    public class Header
    
        public string alg  get; set; 
        public string typ  get; set; 
    

    public class JwtPayload
    
        public string appkey  get; set; 
        public string resource  get; set; 
    



首先,向 CreateToken 方法传递凭据以创建有效负载。然后它调用将有效负载和机密作为参数的 EncodeToken 方法。请记住,我的秘密是一个硬编码的字符串,在应用程序的整个生命周期中都不会改变;所以我知道这不是随机生成数字 1。

第 39 行,标头和有效负载被转换为 base 64 字符串,并由一个点连接在一起,完美地生成了我的令牌的前两部分:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBrZXkiOiIxMjMtNDU2LTc4OS0wIiwicmVzb3VyY2UiOiJnZXRfZ2VvY29kZSJ9

然后,我在第 41 行调用 Sign 方法,该方法请求使用 SHA256 算法对我的令牌进行签名。

Sign 方法接受组合的标头和有效负载作为 str,然后秘密作为密钥传递。

在第 62 行,我使用自定义密钥“testsecret”开始创建签名。

然后我在第 67 行对签名进行 URL 编码,就在返回之前。当我返回它时,第 41 行将令牌的三个部分组合在一起,从而给我留下了一个完美的 JWT……除了密钥最右端的数字“1”。

请帮忙。

【问题讨论】:

【参考方案1】:

这与HttpServerUtility.UrlTokenEncode 的工作方式有关,强调我的:

使用基本 64 位数字将字节数组编码为其等效的字符串表示,可用于在 URL 上传输

您会知道,根据其长度,Base64 字符串将在末尾添加== 不被认为是 URL 安全的,因此被替换为表示计数的整数,在本例中为 1

您可以通过调试和替换下面的行来测试这个...

return System.Web.HttpServerUtility.UrlTokenEncode(signature);

...用这个...

return Convert.ToBase64String(signature);

...并检查返回值。

您会看到它以= 结尾,因此HttpServerUtility.UrlTokenEncode 将其替换为1

【讨论】:

以上是关于URL 编码后,数字 1 随机附加到我的 JWT 密码的末尾的主要内容,如果未能解决你的问题,请参考以下文章

Magento 1 - 删除 url 键/产品 url 中的数字

为啥我不能将数字附加到我的变量?!在斯威夫特 3

如何快速将 json 附加到我的数组中

通过 facebook 登录会附加一些代码来重定向 url

第二个ajax结果没有附加到我的div

为啥字符和正斜杠被附加到我的 NSURL?