我已经搜索了每个角落和裂缝,以解决我的问题,但我似乎无法找到一个。
我有一个使用方法来创建JSON 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行,标题和有效负载转换为基本64字符串,并通过一个点连接在一起,完全生成令牌的前两部分:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBrZXkiOiIxMjMtNDU2LTc4OS0wIiwicmVzb3VyY2UiOiJnZXRfZ2VvY29kZSJ9
然后,我在第41行调用Sign方法,该方法使用SHA256算法请求签署我的令牌。
Sign方法接受组合的头和有效负载作为str,然后秘密作为密钥传递。
在第62行,我开始使用我的自定义键创建签名,这是" testsecret"。
然后,我在返回之前对第67行的签名进行URL编码。当我将它返回时,第41行将令牌的三个部分组合在一起,从而为我留下了完美的JWT ......除了数字" 1"在秘密的最右端。
请帮忙。
答案 0 :(得分:1)
与HttpServerUtility.UrlTokenEncode的工作方式有关,强调我的:
使用基数为64的数字将字节数组编码为等效的字符串表示,可用于在URL上传输
您知道根据其长度,Base64字符串将填充=
附加到末尾。 =
不被视为URL安全,因此将替换为表示计数的整数,在本例中为1
。
您可以通过调试并替换下面的行来测试...
return System.Web.HttpServerUtility.UrlTokenEncode(signature);
......有了......
return Convert.ToBase64String(signature);
...并检查返回值。
您会看到它以=
结尾,因此HttpServerUtility.UrlTokenEncode
会将其替换为1
。