aspnet core 2.1中使用jwt从原理到精通一
2018-10-27 17:43
1331 查看
目录
- 原理;
- 根据原理使用C#语言,生成jwt;
- 自定义验证jwt;
- 使用aspnetcore 中自带的类生成jwt;
学有所得
- 了解jwt原理;
- 使用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相关的验证都是基于上面这些东西
下一章节将讲述:
- 在aspnet core中,自定义jwt管道验证;
- 在aspnet core中,自定义策略验证CommonAuthorizeHandler : AuthorizationHandler<CommonAuthorize>
- 自定义jwt逻辑验证和原生的角色,用户,策略,等进行对比
相关文章推荐
- asp net core2.1如何使用jwt从原理到精通(二)
- 【译】使用Jwt身份认证保护 Asp.Net Core Web Api
- ASP.NET Core 2.1 使用Docker运行的方法步骤
- 【译】使用Jwt身份认证保护 Asp.Net Core Web Api
- ASP.NET Core 使用 JWT 搭建分布式无状态身份验证系统
- 学习 ASP.NET Core 2.1:集成测试中使用 WebApplicationFactory
- ASP.NET Core 使用 JWT 搭建分布式无状态身份验证系统
- ASP.NET Core 1.0 中 EntityFramework 与 PostgreSQL 的使用
- asp.net viewstate视图状态 from 表单Request对象 Response对象 原理跟使用
- asp.net 2.0生命周期 以及Page_Load Page_Init方法使用原理
- ASP.NET Core 1.0 中使用 Swagger 生成文档
- asp.net core 使用EF7 Code First 创建数据库,同时使用命令创建数据库
- asp.net core 使用EntityFrameWork遇到的问题
- 避免在ASP.NET Core中使用服务定位器模式
- 在ASP.NET使用JavaScript显示信息提示窗口实现原理及代码
- ASP.NET温故而知新学习系列之ASP.NET中的多线程编程—.NET下的多线程编程2.1-Thread类的使用
- IHttpHandler中使用Session实现原理[ASP.NET | IHttpHandler |IRequiresSessionState]