我使用以下java脚本代码生成jwt令牌:
<head>
<meta charset="utf-8" />
<script src="js/jquery-1.11.3.min.js"></script>
<script src="js/jquery.base64.js"></script>
<script src="js/aes.js"></script>
<script src="js/aes-json-format.js"></script>
<script src="js/hmac.js"></script>
<script src="js/sha256.js"></script>
<title>Cryptography</title>
</head>
<body>
<div>
<div id="jwtToken" style="font:14px bold; word-wrap: break-word;" />
</div>
<script type="text/javascript">
$(document).ready(function(e){
var data = {
user_type: "tmr",
user_id: "OFhMQVZaS1l0SVFQNGtyaUpoOWRodz09",
accesstoken: "F4111553-802B-B45C-F8DB-627D5933691E"
}
var payload = {
"iat": 101,
"nbf":101,
"exp":161,
"iss":"offers/index",
"jti":'',
"data": data
};
var secret_key = "pa@987";
var n_header = {alg:"HS256",typ:"JWT"};
var enc_header = $.base64.encode(JSON.stringify(n_header));
var enc_payload =$.base64.encode(JSON.stringify(payload));
console.log("---- encrypted header---")
console.log(enc_header);
console.log("---- encrypted payload---")
console.log(payload);
var token = enc_header + "." + enc_payload;
var sh_h256 = CryptoJS.HmacSHA256(token, secret_key);
var jwt_enc_signature = $.base64.encode(sh_h256);
token = token + "." + jwt_enc_signature;
console.log("---- JWT Signature ---");
console.log(jwt_enc_signature);
console.log("----- JWT Token ------");
console.log(token);
document.getElementById('jwtToken').innerHTML = token;
});
</script>
</body>
上面的代码让我得到以下标记:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjEwMSwibmJmIjoxMDEsImV4cCI6MTYxLCJpc3MiOiJvZmZlcnMvaW5kZXgiLCJqdGkiOiIiLCJkYXRhIjp7InVzZXJfdHlwZSI6InRtciIsInVzZXJfaWQiOiJPRmhNUVZaYVMxbDBTVkZRTkd0eWFVcG9PV1JvZHowOSIsImFjY2Vzc3Rva2VuIjoiRjQxMTE1NTMtODAyQi1CNDVDLUY4REItNjI3RDU5MzM2OTFFIn19.YjdlNTcxMTliNGM0OTA2ZTVmYzY2NTlkZmQ1ZTk3YmQ0NDk4MGJmZGI3YzZlZjUzNGZmZTk3YmRmYjAwNmUyZA==
我正在使用以下c#代码生成相同的令牌:
static void test()
{
dynamic data = new System.Dynamic.ExpandoObject();
data.user_type = "tmr";
data.user_id = "OFhMQVZaS1l0SVFQNGtyaUpoOWRodz09";
data.accesstoken = "F4111553-802B-B45C-F8DB-627D5933691E";
Object payload = new Dictionary<string, object>()
{
{ "iat", 101 },
{ "nbf", 101 },
{ "exp", 161 },
{ "iss", "offers/index" },
{ "jti", "" },
{ "data", data }
};
var secret_key = "pa@987";
dynamic n_header = new System.Dynamic.ExpandoObject();
n_header.alg = "HS256";
n_header.typ = "JWT";
byte[] headerBytes = Encoding.ASCII.GetBytes(JsonConvert.SerializeObject(n_header));
byte[] payloadBytes = Encoding.ASCII.GetBytes(JsonConvert.SerializeObject(payload));
var enc_header = Base64UrlEncode(headerBytes);
var enc_payload = Base64UrlEncode(payloadBytes);
var token = enc_header + "." + enc_payload;
var sh_h256 = JsonWebTokenConvert.Converter.CreateToken(token, secret_key);
var jwt_enc_signature = Base64UrlEncode(sh_h256);
token = token + "." + jwt_enc_signature;
Console.WriteLine(token);
}
private static string Base64UrlEncode(byte[] input)
{
var output = Convert.ToBase64String(input);
output = output.Split('=')[0]; // Remove any trailing '='s
output = output.Replace('+', '-'); // 62nd char of encoding
output = output.Replace('/', '_'); // 63rd char of encoding
return output;
}
public static byte[] CreateToken(string message, string secret)
{
secret = secret ?? "";
var encoding = new System.Text.ASCIIEncoding();
byte[] keyByte = encoding.GetBytes(secret);
byte[] messageBytes = encoding.GetBytes(message);
string base64Message = Convert.ToBase64String(messageBytes);
byte[] base64Bytes = encoding.GetBytes(base64Message);
using (var hmacsha256 = new HMACSHA256(keyByte))
{
byte[] hashmessage = hmacsha256.ComputeHash(base64Bytes);
return hashmessage;
}
}
这让我跟随的标记与从java脚本代码生成的标记不匹配:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjEwMSwibmJmIjoxMDEsImV4cCI6MTYxLCJpc3MiOiJvZmZlcnMvaW5kZXgiLCJqdGkiOiIiLCJkYXRhIjp7InVzZXJfdHlwZSI6InRtciIsInVzZXJfaWQiOiJPRmhNUVZaYVMxbDBTVkZRTkd0eWFVcG9PV1JvZHowOSIsImFjY2Vzc3Rva2VuIjoiRjQxMTE1NTMtODAyQi1CNDVDLUY4REItNjI3RDU5MzM2OTFFIn19.EZtxFXJTwDExZFJuRcPppmY7d97MsUcfpxq1JI1VSBw
我对此问题毫无头绪。有人可以帮助我朝正确的方向前进。
答案 0 :(得分:0)
在JavaScript版本中,您对标头和有效负载执行Base64编码,并将其作为字符串放在一起:
var enc_header = $.base64.encode(JSON.stringify(n_header));
var enc_payload =$.base64.encode(JSON.stringify(payload));
var token = enc_header + "." + enc_payload;
然后计算密钥并对其执行base64编码:
var sh_h256 = CryptoJS.HmacSHA256(token, secret_key);
var jwt_enc_signature = $.base64.encode(sh_h256);
在C#中,您在创建签名之前执行与JS相同的操作:
var enc_header = Base64UrlEncode(headerBytes);
var enc_payload = Base64UrlEncode(payloadBytes);
var token = enc_header + "." + enc_payload;
但不是加密令牌,而是调用CreateToken
var sh_h256 = JsonWebTokenConvert.Converter.CreateToken(token, secret_key);
但遗憾的是,您的CreateToken
函数在计算签名之前再次对消息进行base64编码:
public static byte[] CreateToken(string message, string secret)
{
...
string base64Message = Convert.ToBase64String(messageBytes);
...
using (var hmacsha256 = new HMACSHA256(keyByte))
{
byte[] hashmessage = hmacsha256.ComputeHash(base64Bytes);
return hashmessage;
}
}
导致两个版本中的签名不同。
所述您必须像在JS版本和签名的do base64Url编码中那样创建签名,然后将其连接到令牌。
所以你的JS版本看起来是正确的,但我无法在https://jwt.io/introduction/
上验证令牌