当前位置: 首页 > article >正文

.Net Core 中间件验签

文章目录

    • 为什么是用中间件而不是筛选器?
    • 代码实现
    • 技术要点
      • context.Request.EnableBuffering()
      • 指针问题
    • 小结

为什么是用中间件而不是筛选器?

在这里插入图片描述

为什么要用中间件验签,而不是筛选器去验签?
1、根据上图我们可以看到,中间件在筛选器之前,而筛选往下就是我们写业务逻辑代码的控制器了。这就大大增加了我们被攻击的风险。
2、用筛选器我们需要在每个控制器上都添加相应的标识,如果需要校验的sign的控制器多的话,就增加了很多不必要的工作量,和风险,如果某个控制器一时疏忽忘记加筛选器的话就有可能会被攻击。

筛选器一般都是当数据得到信任的时候做验证,例如用户登录了,做功能的权限判定,中间件判定非信任数据

代码实现

 /// <summary>
 /// 验签中间件
 /// </summary>
 public class SignatureMiddleware
 { /// <summary>
   /// 用户服务
   /// </summary>
     public UserService _userService { get; set; }
     private readonly RequestDelegate _next;
    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="next">上下文</param>
    /// <param name="userService">用户服务注入</param>
     public SignatureMiddleware(RequestDelegate next, UserService userService)
     {
         _next = next;
         _userService = userService;
     }
     /// <summary>
     /// 管道委托
     /// </summary>
     /// <param name="context">请求</param>
     /// <returns></returns>
     public async Task Invoke(HttpContext context)
     {
         if (context.Request.Path.Value.StartsWith("/api/Order"))
         {
           
             // 验证签名
             var isValidSignature = await ValidateSignatureAsync(context);

             if (isValidSignature.Item1)
             {
                 
                 await _next(context);
             }
             else
             {
                 context.Response.StatusCode = 403;
                 await context.Response.WriteAsJsonAsync(AlwaysResult.Error(isValidSignature.Item2));
             }
         }
         else
         {
             await _next(context);
         }
     }

     private async Task<(bool, string)> ValidateSignatureAsync(HttpContext context)
     {
         context.Request.EnableBuffering();//倒带
         string Postbody = string.Empty;
         string sign = context.Request.Headers[GlobalContext.SystemConfig.OpenApiSettings.SignName].ParseToString();
         string timestamp = context.Request.Headers[GlobalContext.SystemConfig.OpenApiSettings.Timestamp].ParseToString();
         string appkey = context.Request.Headers[GlobalContext.SystemConfig.OpenApiSettings.Appkey].ParseToString();
         //先根据Appkey查询这个账户的状态:
             UserExtend user = await _userService.GetForm(appkey);
         if (user != null)
         {
             context.Request.Body.Position = 0;
             var readResult = await context.Request.BodyReader.ReadAsync();
             context.Request.BodyReader.AdvanceTo(readResult.Buffer.Start, readResult.Buffer.End);
              Postbody = Encoding.UTF8.GetString(readResult.Buffer.FirstSpan);
             string checksign = DESEncrypt.MD5(appkey + timestamp + Postbody + user.F_Account + appkey).ToLower();
             if (!checksign.Equals(sign))
             {
                 return (false, "验签失败!");
             }
             else
             {
                 context.Request.Body.Position = 0;//指针回拨
                 return (true, "");
                
             }
         }
         else
         {
             return (false, "非法签名!");
         }
     }



 }

技术要点

context.Request.EnableBuffering()

ValidateSignatureAsync 方法为验证签名方法,方法内第一行中的:context.Request.EnableBuffering();的作用是允许http请求中的body重复读取,如果不加这个方法当数据在验签过程中读取出来之后到了控制器时,控制器中获取到的body就会是空值

指针问题

context.Request.Body.Position ;
代码中用到了两次,第一次使用的时候是将指针指向body的第一位。当读取出数据之后,指针会由第一位移动到最后一位,因此我们在读取完验签完成之后需要把指针从最后以为拨回到第一位。如果没有验签通过也就没有那个必要了。

小结

在学习过程中我们不仅要知其然还要知其所以然。
中间件:用于过滤非信任数据
过滤器:用于判定受信任的安全的数据


http://www.kler.cn/a/274295.html

相关文章:

  • iterm2 focus时灰色蒙层出现的解决办法
  • Flutter组件————Container
  • 基于Spring Boot的房屋租赁管理系统
  • clickhouse-数据库引擎
  • Nginx的stream模块代理四层协议TCP的流量转发
  • React图标库: 使用React Icons实现定制化图标效果
  • 华为组网:核心交换机旁挂防火墙,基于ACL重定向配置实验
  • Maven项目如何导入依赖包
  • Nginx安装教程
  • Springboot+Redis:实现缓存 减少对数据库的压力
  • fastjson反序列化攻略
  • 解决重装系统之后,开始菜单找不到Anaconda3相关图标
  • 快速从0-1完成聊天室开发——环信ChatroomUIKit功能详解
  • Java-SpringAop 编程式事物实现
  • 如何在三个简单步骤中为对象检测标注图像
  • C语言---指针的两个运算符:点和箭头
  • Java 多线程(抢CPU)
  • 面试算法-51-翻转二叉树
  • 【C语言进阶篇】自定义类型:结构体(上)
  • 堆排序(数据结构)
  • SpringBoot项目串口通讯之jSerialComm
  • 什么是多模态学习?
  • 代码随想录|Day21|回溯01|77.组合
  • 面试算法-47-有效的括号
  • 基于”Python+”多技术融合在蒸散发与植被总初级生产力估算中的应用教程
  • Unity类银河恶魔城学习记录11-2 p104 Inventoty源代码