Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/410.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 签约JWT-我做错了吗?_Javascript_Jwt - Fatal编程技术网

Javascript 签约JWT-我做错了吗?

Javascript 签约JWT-我做错了吗?,javascript,jwt,Javascript,Jwt,出于教育目的,我正在尝试用JavaScript制作一个JWT生成器。有一个工具可以创建和/或验证JWT 我正在努力使我的结果与验证器的结果相匹配。问题是签名 这是我的密码: function base64url(input) { return btoa(typeof input === 'string' ? input : JSON.stringify(input)) .replace(/=+$/, '') .replace(/\+/g, '-')

出于教育目的,我正在尝试用JavaScript制作一个JWT生成器。有一个工具可以创建和/或验证JWT

我正在努力使我的结果与验证器的结果相匹配。问题是签名

这是我的密码:

function base64url(input) {
    return btoa(typeof input === 'string' ? input : JSON.stringify(input))
        .replace(/=+$/, '')
        .replace(/\+/g, '-')
        .replace(/\//g, '_');
}

const JWT = {
    encode(header, payload, secret) {
        const unsigned = [base64url(header), base64url(payload)].join('.');

        return [unsigned, base64url(sha256.hmac(secret, unsigned))].join('.');
    }
};
为了加密HMACSHA256,我使用了带有
SHA256.HMAC(key,value)
prototype的库。我将它与在线工具进行了比较,结果很好

现在,我用以下代码测试它:

const jwt = JWT.encode(
    {
        alg: 'HS256',
        typ: 'JWT'
    },
    123,
    'xxx'
);
我得到的结果是:

EYJHBGCOIJIUZI1NIISINR5CCI6IKPXVCj9.MTIz.NzhlNTFmYzUxOGQ2YjNlZDFiOTM0ZGRhOTUwNDFmMzEwMzdlNmZkZWRhNGFlMjdlNDU3ZTZhNWRhYjQ1YzFiMQ

另一方面,结果是:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.MTIz.eOUfxRjWs-0BK03ALQFMQN-b97aSuJ-RX5qXatFwbE

如您所见,JWT的三个块中的两个在我的结果和结果中是相同的。签名是不同的,如果你问我,它生成的签名是惊人的短。该工具还将我自己的JWT标记为无效

我使用在线HMAC SHA256生成器进行了检查,我的代码似乎创建了一个有效的签名,因此:

base64url(sha256.hmac('xxx', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.MTIz')) ===
'NzhlNTFmYzUxOGQ2YjNlZDFiOTM0ZGRhOTUwNDFmMzEwMzdlNmZkZWRhNGFlMjdlNDU3ZTZhNWRhYjQ1YzFiMQ'

只是坏了还是用其他方法做的?

我不会说你做错了,但你错过了一个小但重要的细节。 来自的结果是正确的,您计算的散列也正确。但是使用哈希创建的签名不正确

使用
sha256.hmac(secret,unsigned)
计算的哈希值是一个大数字,但函数的返回值是该大数字的十六进制字符串表示形式。对于签名,您需要对原始数字进行base64url编码,而不是它的字符串表示形式

我修改了您的代码,以便将哈希值直接编码到base64url(node.js版本):

或者,如果您不使用node.js,您可以改为使用它(正如Robo Robok所建议的):

结果是一个令牌,它与使用以下方法创建的令牌相同:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.MTIz.eOUfxRjWs-0BK03ALQFMQN-b97aSuJ-RX5qXatFwbE


另请参见,其中我解释了比较不同工具结果的步骤。

我也想知道。它只发生在对称类型
const JWT = {
    encode(header, payload, secret) {
        const unsigned = [base64url(header), base64url(payload)].join('.');
        const hash  = sha256.hmac(secret, unsigned);
        console.log(hash);        
        var signature = new Buffer.from(hash, 'hex').toString('base64').replace(/\+/g,'-').replace(/\=+$/m,'');

        return [unsigned, signature].join('.');
    }
};
const JWT = {
    encode(header, payload, secret) {
        const unsigned = [base64url(header), base64url(payload)].join('.');

        return [unsigned, base64url(sha256.hmac(secret, unsigned).replace(/\w{2}/g, byte => String.fromCharCode(parseInt(byte, 16))))].join('.');
    }
};