.Net中使用JWT

.Net中使用JWT

一、JWT数据结构

实际的 JWT 大概就像下面这样。

截图

它是一个很长的字符串,中间用点(.)分隔成三个部分。注意,JWT 内部是没有换行的,这里只是为了便于展示,将它写成了几行。

JWT 的三个部分依次如下。

Header(头部包含算法信息)
Payload(负载包含实际传递信息)
Signature(对前面两部分的签名)

写成一行,就是下面这样

截图

二、怎么生成JWT

using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;

//payload部分
List<Claim> claims = new List<Claim>();
claims.Add(new Claim("zidingyi", "自定义"));
claims.Add(new Claim(ClaimTypes.NameIdentifier, "11111"));
claims.Add(new Claim(ClaimTypes.Name, "zebary"));
claims.Add(new Claim(ClaimTypes.Role, "admin"));
claims.Add(new Claim(ClaimTypes.Role, "user"));

//服务器私钥不能太短
string key = "dkdls()dlfj%sldfj#sdlfnbmlkepkkqaopxd@9094";
//超时时间
DateTime expire = DateTime.Now.AddHours(1);

//编码
byte[] secBytes = Encoding.UTF8.GetBytes(key);
var secKey = new SymmetricSecurityKey(secBytes);
var credentials = new SigningCredentials(secKey, SecurityAlgorithms.HmacSha256Signature);
var tokenDescriptor = new JwtSecurityToken(claims: claims, expires: expire, signingCredentials: credentials);
string jwt = new JwtSecurityTokenHandler().WriteToken(tokenDescriptor);

注意JWT中payload是明文保存的,不要把不能被客户端知道的信息放到JWT中

我们可以做个测试,对编码之后的jwt不用私钥直接解码

//不使用私钥,直接解码
string[] segments = jwt.Split('.');
string head = JwtDecode(segments[0]);
string payload = JwtDecode(segments[1]);
Console.WriteLine($"head:{head}");
Console.WriteLine($"payload:{payload}");

string JwtDecode(string s)
{
    s = s.Replace('-', '+').Replace('_', '/');
    switch (s.Length % 4)
    {
        case 2:
            s += "==";
            break;
        case 3:
            s += "=";
            break;
    }

    var bytes = Convert.FromBase64String(s);
    return Encoding.UTF8.GetString(bytes);
}

截图

三、怎么校验是否篡改及获取payload信息

//使用私钥验证签名是否篡改
string seckey = "dkdls()dlfj%sldfj#sdlfnbmlkepkkqaopxd@9094";
JwtSecurityTokenHandler tokenHandler = new();
TokenValidationParameters valParams = new();
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(seckey));
valParams.IssuerSigningKey = securityKey;
valParams.ValidateIssuer = false;
valParams.ValidateAudience = false;

//验证是否篡改,如果篡改会报异常
ClaimsPrincipal claimsPrincipal = tokenHandler.ValidateToken(jwt,valParams,out SecurityToken secToken);
foreach(var claim in claimsPrincipal.Claims)
{
    Console.WriteLine($"{claim.Type}={claim.Value}");
}

截图

以上代码在.Net 6 和.Net Framework 4.6中运行过其他没有试过

posted @ 2023-02-19 10:30  夜晚的斑马鱼  阅读(552)  评论(0)    收藏  举报