C#手动构建JWT令牌不起作用

C#手动构建JWT令牌不起作用,c#,token,jwt,C#,Token,Jwt,我试图通过构建这三个组件,然后将它们组合起来,手动构建一个JWT令牌。根据这一点:该代币分为三个部分;JWT头、有效负载和签名。下面的代码似乎成功地生成了前两个。但签名不正确: public async Task<string> GetJWTToken(string user) { var now = DateTime.UtcNow; //constructing part 1: header.Encode() JwtHeader jwtHeader = n

我试图通过构建这三个组件,然后将它们组合起来,手动构建一个JWT令牌。根据这一点:该代币分为三个部分;JWT头、有效负载和签名。下面的代码似乎成功地生成了前两个。但签名不正确:

public async Task<string> GetJWTToken(string user)
{

    var now = DateTime.UtcNow;
    //constructing part 1: header.Encode()
    JwtHeader jwtHeader = new JwtHeader();
    jwtHeader.Add("alg", JwtAlgorithms.HMAC_SHA512);
    var partOne = jwtHeader.Base64UrlEncode();

    //constructing part 2: payload.Encode  
    JwtPayload payload = new JwtPayload();
    payload.Add("sub", user);
    payload.Add("nbf",ConvertToUnixTimestamp(now.AddMinutes(-10)));
    var partTwo = payload.Base64UrlEncode();

    //constructing part 3: HS512(part1 + "." + part2, key)
    var tobeHashed = partOne + "." + partTwo;
    var sha = new HMACSHA512(Encoding.UTF8.GetBytes(ConfigurationHelper.AppSettings("JWTOfferKey")));
    var hashedByteArray = sha.ComputeHash(Encoding.UTF8.GetBytes(tobeHashed));
    StringBuilder partThree = new StringBuilder();

    foreach (var hashedByte in hashedByteArray)
    {
        partThree.Append(hashedByte.ToString("X2"));
    }

    //token = part1 + "." + part2 + "." + part3
    var tokenString = partOne + "." + partTwo + "." + Base64Encode(partThree.ToString());

    return tokenString;
}

public static double ConvertToUnixTimestamp(DateTime date)
{
    DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
    TimeSpan diff = date.ToUniversalTime() - origin;
    return Math.Floor(diff.TotalSeconds);
}

public static string Base64Encode(string plainText)
{
    var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
    return System.Convert.ToBase64String(plainTextBytes);
}
公共异步任务GetJWTToken(字符串用户)
{
var now=DateTime.UtcNow;
//构造第1部分:header.Encode()
JwtHeader JwtHeader=新JwtHeader();
jwtHeader.Add(“alg”,JwtAlgorithms.HMAC_SHA512);
var partOne=jwtHeader.Base64UrlEncode();
//构造第2部分:有效载荷.编码
JwtPayload payload=新的JwtPayload();
有效载荷。添加(“子”,用户);
payload.Add(“nbf”,converttounix时间戳(now.AddMinutes(-10));
var partTwo=payload.Base64UrlEncode();
//构造第3部分:HS512(第1部分+第2部分,键)
var tobeHashed=第1部分+“+”第2部分;
var sha=new-HMACSHA512(Encoding.UTF8.GetBytes(ConfigurationHelper.AppSettings(“JWTOfferKey”));
var hashedByteArray=sha.ComputeHash(Encoding.UTF8.GetBytes(tobeHashed));
StringBuilder第三部分=新建StringBuilder();
foreach(hashedByteArray中的var hashedByte)
{
Append(hashedByte.ToString(“X2”);
}
//令牌=part1+“+part2+”+part3
var-tokenString=partOne+““+partTwo+”+Base64Encode(partThree.ToString());
返回令牌字符串;
}
公共静态双时间戳(日期时间日期)
{
DateTime origin=新的DateTime(1970,1,1,0,0,0,0,DateTimeKind.Utc);
TimeSpan diff=date.ToUniversalTime()-原点;
返回数学楼层(差异总秒);
}
公共静态字符串base64编码(字符串明文)
{
var plainTextBytes=System.Text.Encoding.UTF8.GetBytes(明文);
返回System.Convert.ToBase64String(明文字节);
}
有人知道最后一部分的构造有什么问题吗

最后一部分的构造有什么问题

您需要对签名哈希值进行Base64Url编码

public Task<string> GetJWTToken(string user) {

    //...other code removed for brevity

    //constructing part 3: HS512(part1 + "." + part2, key)
    var tobeHashed = string.Join(".", partOne, partTwo);
    var sha = new HMACSHA512(Encoding.UTF8.GetBytes(ConfigurationHelper.AppSettings("JWTOfferKey")));
    var hashedByteArray = sha.ComputeHash(Encoding.UTF8.GetBytes(tobeHashed));

    //You need to base64UrlEncode the signature hash value
    var partThree = Base64UrlEncode(hashedByteArray);

    //Now construct the token
    var tokenString = string.Join(".", tobeHashed, partThree);

    //await was not used so no need for `async` keyword. Just return task
    return Task.FromResult(tokenString);
}

// from JWT spec
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任务GetJWTToken(字符串用户){
//…为简洁起见,删除了其他代码
//构造第3部分:HS512(第1部分+第2部分,键)
var tobeHashed=string.Join(“.”,第一部分,第二部分);
var sha=new-HMACSHA512(Encoding.UTF8.GetBytes(ConfigurationHelper.AppSettings(“JWTOfferKey”));
var hashedByteArray=sha.ComputeHash(Encoding.UTF8.GetBytes(tobeHashed));
//您需要对签名哈希值进行Base64Url编码
var part three=Base64UrlEncode(hashedByteArray);
//现在构造令牌
var tokenString=string.Join(“.”,tobeHashed,第三部分);
//未使用wait,因此不需要'async'关键字。只需返回任务即可
返回Task.FromResult(令牌字符串);
}
//来自JWT规范
专用静态字符串Base64UrlEncode(字节[]输入){
var输出=Convert.tobase64字符串(输入);
output=output.Split('=')[0];//删除任何尾随'='
output=output.Replace('+','-');//编码的第62个字符
output=output.Replace('/',''');//编码的第63个字符
返回输出;
}