时间戳作用
客户端在向服务端接口进行请求, 如果请求信息进行了加密处理, 被第三方截取到请求包, 可以使用该请求包进行重复请求操作. 如果服务端不进行防重放攻击, 就会服务器压力增大, 而使用时间戳的方式可以解决这一问题.
上一篇讲到 JWT 安全验证操作, 现在结合时间戳进行防重复攻击和被第三方抓包工具截取到 Headers 中 token, 进行模拟请求操作.
防篡改
一般使用的方式就是把参数拼接, 当前项目 AppKey, 双方约定的 "密钥", 加入到 Dictionary 字典集中, 按 ABCD 顺序进行排序, 最后在 MD5 + 加密. 客户端将加密字符串和请求参数一起发送给服务器. 服务器按照
上述规则拼接加密后, 与传入过来的加密字符串比较是否相等
防复用
上面的方式进行加密, 就无法解决防复用的问题, 这时需要在客户端和服务端分别生成 UTC 的时间戳, 这个 UTC 是防止你的客户端与服务端不在同一个时区, 呵呵, 然后把时间戳 timestamp 拼在密文里就可以了, 至于防复用的有效性
下面进入正题, 编码启动
创建 DESCryption 帮助类
- public class DESCryption
- { /// <summary>
- ///// 注意了, 是 8 个字符, 64 位
- /// </summary>
- private static string PrivateRsa = ConfigurationManager.AppSettings["PrivateRsa"];
- /// <summary>
- ///// 注意了, 是 8 个字符, 64 位
- /// </summary>
- private static string PublicRsa = ConfigurationManager.AppSettings["PublicRsa"];
- /// <summary>
- /// 加密
- /// </summary>
- /// <param name="data"></param>
- /// <returns></returns>
- public static string Encode(string data)
- {
- byte[] byKey = Encoding.ASCII.GetBytes(PrivateRsa);
- byte[] byIV = Encoding.ASCII.GetBytes(PublicRsa);
- DESCryptoServiceProvider cryptoProvider = new DESCryptoServiceProvider();
- int i = cryptoProvider.KeySize;
- MemoryStream ms = new MemoryStream();
- CryptoStream cst = new CryptoStream(ms, cryptoProvider.CreateEncryptor(byKey, byIV), CryptoStreamMode.Write);
- StreamWriter sw = new StreamWriter(cst);
- sw.Write(data);
- sw.Flush();
- cst.FlushFinalBlock();
- sw.Flush();
- return Convert.ToBase64String(ms.GetBuffer(), 0, (int)ms.Length);
- }
- /// <summary>
- /// 解密
- /// </summary>
- /// <param name="data"></param>
- /// <returns></returns>
- public static string Decode(string data)
- {
- byte[] byKey = Encoding.ASCII.GetBytes(PrivateRsa);
- byte[] byIV = Encoding.ASCII.GetBytes(PublicRsa);
- byte[] byEnc;
- try
- {
- byEnc = Convert.FromBase64String(data);
- }
- catch
- {
- return null;
- }
- DESCryptoServiceProvider cryptoProvider = new DESCryptoServiceProvider();
- MemoryStream ms = new MemoryStream(byEnc);
- CryptoStream cst = new CryptoStream(ms, cryptoProvider.CreateDecryptor(byKey, byIV), CryptoStreamMode.Read);
- StreamReader sr = new StreamReader(cst);
- return sr.ReadToEnd();
- }
- }
然后在 MyAuthorizeAttribute 加上时间戳验证方法
将 DESC 签名时间字符串 当作请求传入
如果传入的时间戳小于服务器当前时间 返回 false 提示权限不足
如果传入的时间戳大于服务器当前时间 返回 true 可以正常访问
完美方案就是将 redis 中 jwtToken 设置过期时间 各位兄台希望我补充完整,
请留言 -- 我会及时更新 GitHub 将这个 dmeo 补充完整
- // 请求参数
- string requestTime = httpContext.Request["rtime"]; // 请求时间经过 DESC 签名
- if (string.IsNullOrEmpty(requestTime))
- return false;
- // 请求时间 DESC 解密后加上时间戳的时间即该请求的有效时间
- DateTime Requestdt = DateTime.Parse(DESCryption.Decode(requestTime)).AddMinutes(int.Parse(TimeStamp));
- DateTime Newdt = DateTime.Now; // 服务器接收请求的当前时间
- if (Requestdt < Newdt)
- {
- return false;
- }
- else
- {
- // 进行其他操作
- var userinfo = JwtHelp.GetJwtDecode(authHeader);
- // 举个例子 生成 jwtToken 存入 redis 中
- // 这个地方用 jwtToken 当作 key 获取实体 val 然后看看 jwtToken 根据 redis 是否一样
- if (userinfo.UserName == "admin" && userinfo.Pwd == "123")
- return true;
- }
大家还有什么需要了解的新手教程知识点, 可以留言给我. 我会在三天内给大家写一份简单的教学 demo 出来
后期 ASP.NET API,ASP.NET Core,Java 教程都可以.
https://github.com/yaols/JWT.MvcDemo
来源: https://www.cnblogs.com/xiaobai123/p/9243809.html