您的位置:首页 > 编程语言 > ASP

aspnet core 2.1中使用jwt从原理到精通一

2018-10-27 17:43 1331 查看

 

目录

  1. 原理;
  2. 根据原理使用C#语言,生成jwt;
  3. 自定义验证jwt;
  4. 使用aspnetcore 中自带的类生成jwt;

学有所得

  1. 了解jwt原理;
  2. 使用C#轻松实现jwt生成和验证

原理

jwt对所有语言都是通用的,只要知道秘钥,另一一种语言有可以对jwt的有效性进行判断;

jwt的组成;Header部分Base64转化.Payload部分Base64转化.使用HS256方式根据秘钥对前面两部分进行加密后再Base64转化,其中使用的hs256加密是header部分指定的,也可以通过官网的查看,如下图:

/// <summary>
/// Token上下文,负责token的创建和验证
/// </summary>
public class TokenContext
{
/// <summary>
/// 秘钥,可以从配置文件中获取
/// </summary>
public static string securityKey = "GQDstclechengroberbojPOXOYg5MbeJ1XT0uFiwDVvVBrk";

/// <summary>
/// 创建jwttoken,源码自定义
/// </summary>
/// <param name="payLoad"></param>
/// <param name="header"></param>
/// <returns></returns>
public static string CreateToken(Dictionary<string, object> payLoad,int expiresMinute, Dictionary<string, object> header = null)
{
if (header == null)
{
header = new Dictionary<string, object>(new List<KeyValuePair<string, object>>() {
new KeyValuePair<string, object>("alg", "HS256"),
new KeyValuePair<string, object>("typ", "JWT")
});
}
//添加jwt可用时间(应该必须要的)
var now = DateTime.UtcNow;
payLoad["nbf"] = ToUnixEpochDate( now);//可用时间起始
payLoad["exp"] = ToUnixEpochDate(now.Add(TimeSpan.FromMinutes(expiresMinute)));//可用时间结束

var encodedHeader = Base64UrlEncoder.Encode(JsonConvert.SerializeObject(header));
var encodedPayload = Base64UrlEncoder.Encode(JsonConvert.SerializeObject(payLoad));

var hs256 = new HMACSHA256(Encoding.ASCII.GetBytes(securityKey));
var encodedSignature = Base64UrlEncoder.Encode(hs256.ComputeHash(Encoding.UTF8.GetBytes(string.Concat(encodedHeader, ".", encodedPayload))));

var encodedJwt = string.Concat(encodedHeader, ".", encodedPayload, ".", encodedSignature);
return encodedJwt;
}

/// <summary>
/// 创建jwtToken,采用微软内部方法,默认使用HS256加密,如果需要其他加密方式,请更改源码
/// 返回的结果和CreateToken一样
/// </summary>
/// <param name="payLoad"></param>
/// <param name="expiresMinute">有效分钟</param>
/// <returns></returns>
public static string CreateTokenByHandler(Dictionary<string, object> payLoad, int expiresMinute)
{

var now = DateTime.UtcNow;

// Specifically add the jti (random nonce), iat (issued timestamp), and sub (subject/user) claims.
// You can add other claims here, if you want:
var claims = new List<Claim>();
foreach (var key in payLoad.Keys)
{
var tempClaim = new Claim(key, payLoad[key]?.ToString());
claims.Add(tempClaim);
}

// Create the JWT and write it to a string
var jwt = new JwtSecurityToken(
issuer: null,
audience: null,
claims: claims,
notBefore: now,
expires: now.Add(TimeSpan.FromMinutes(expiresMinute)),
signingCredentials: new SigningCredentials(new SymmetricSecurityKey(Encoding.ASCII.GetBytes(securityKey)), SecurityAlgorithms.HmacSha256));
var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt);
return encodedJwt;
}

/// <summary>
/// 验证身份 验证签名的有效性,
/// </summary>
/// <param name="encodeJwt"></param>
/// <param name="validatePayLoad">自定义各类验证; 是否包含那种申明,或者申明的值, </param>
/// 例如:payLoad["aud"]?.ToString() == "roberAuddience";
/// 例如:验证是否过期 等
/// <returns></returns>
public static bool Validate(string encodeJwt,Func<Dictionary<string,object>,bool> validatePayLoad)
{
var success = true;
var jwtArr = encodeJwt.Split('.');
var header = JsonConvert.DeserializeObject<Dictionary<string, object>>(Base64UrlEncoder.Decode(jwtArr[0]));
var payLoad = JsonConvert.DeserializeObject<Dictionary<string, object>>(Base64UrlEncoder.Decode(jwtArr[1]));

var hs256 = new HMACSHA256(Encoding.ASCII.GetBytes(securityKey));
//首先验证签名是否正确(必须的)
success = success && string.Equals(jwtArr[2], Base64UrlEncoder.Encode(hs256.ComputeHash(Encoding.UTF8.GetBytes(string.Concat(jwtArr[0], ".", jwtArr[1])))));
if (!success)
{
return success;//签名不正确直接返回
}
//其次验证是否在有效期内(也应该必须)
var now = ToUnixEpochDate(DateTime.UtcNow);
success = success && (now >= long.Parse(payLoad["nbf"].ToString()) && now < long.Parse(payLoad["exp"].ToString()));

//再其次 进行自定义的验证
success = success && validatePayLoad(payLoad);

return success;
}
/// <summary>
/// 获取jwt中的payLoad
/// </summary>
/// <param name="encodeJwt"></param>
/// <returns></returns>
public static Dictionary<string ,object> GetPayLoad(string encodeJwt)
{
var jwtArr = encodeJwt.Split('.');
var payLoad = JsonConvert.DeserializeObject<Dictionary<string, object>>(Base64UrlEncoder.Decode(jwtArr[1]));
return payLoad;
}
public static long ToUnixEpochDate(DateTime date) =>
(long)Math.Round((date.ToUniversalTime() - new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero)).TotalSeconds);
}
View Code 以上就是jwt的基本内容,它确实很简单,不要被aspnet core中的各种写法给搞晕了,只要是jwt相关的验证都是基于上面这些东西

下一章节将讲述:

  1. 在aspnet core中,自定义jwt管道验证;
  2. 在aspnet core中,自定义策略验证CommonAuthorizeHandler : AuthorizationHandler<CommonAuthorize>
  3. 自定义jwt逻辑验证和原生的角色,用户,策略,等进行对比

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: