.Net core WebApi 实现对httpcontext中request数据包自定义

本文介绍了如何在.NET Core 5的WebApi中使用ActionFilter实现对HTTP请求数据的DES加密,并解决了在ActionExecutingContext中访问参数的问题。同时提到Swagger调试时的便利性提升。

前言

最近公司有个WebApi接口打算用.net core重构下,由于业务需求,要求对传输过程中所有数据进行DES加密,之前的接口是在每个Action中进行加解密操作,这个场景很容易想到.net core中的ActionFilter过滤器,可以非常完美的解决这一问题,于是进行了改造。

运行环境

运行环境:.Net 5
开发环境:VS2019 16.8.2

ActionFilter介绍

为什么可以用ActionFilter来实现这一功能,看一下官方的说明:.net core 中的过滤器允许在执行管道中的特定阶段之前或之后运行代码。可以对全局,也可以对每个控制器或每个操作配置过滤器。
在这里插入图片描述
不同的过滤器类型在管道中的不同阶段执行,因此具有各自的场景。根据执行的任务以及执行的请求在管道中的位置,选择要创建的过滤器类型。过滤器在管道中执行,有时也称为过滤管道,在asp .net core 中选择要执行的操作后,执行相应的过滤器。
在这里插入图片描述
从上图可以看出一共有四种过滤器:
1、授权过滤器(Authorization filter):用于确定当前请求用户是否被授权。
2、资源过滤器(Resource filter):在授权之后第一个处理请求的过滤器,也是最后一个在请求离开过滤管道时结束请求的过滤器。
3、操作过滤器(Action filter):包装对单个操作方法的调用,并且可以处理传递到操作的参数以及从操作返回的操作结果。
4、异常过滤器(Exception filter):用于对应用程序中未处理的异常应用全局策略。
5、结果过滤器(Result filter):包装单个操作结果的执行,并且尽在操作执行成功时运行。它们必须是围绕视图执行或格式化程序执行的逻辑的理想选择。

ActionFilter

OnActionExecuting:在执行Action之前调用
OnActionExecuted:在执行Action之后调用

public class DESHandlerFilter : IActionFilter
    {
        public void OnActionExecuted(ActionExecutedContext context)
        {
            
        }

        public void OnActionExecuting(ActionExecutingContext context)
        {
            
        }
    }

所以只需要在上述过滤器中实现相应的DES加解密方法即可。

在这里有个坑,我们正常的理解是需要去context中拿到httpcontext来获取传入的参数,但实际发现context.HttpContext.Request.Body中是null,经过查阅相关资料发现,微软官方文档有这么一句话:【HttpContext 不是线程安全型。 在处理请求之外读取或写入 HttpContext 的属性可能会导致 NullReferenceException。
其实这个也很好理解,http请求中的参数只允许最终的执行操作方法来获取,也就是说只允许被获取一次。所以在这里想直接对HttpContext中的参数进行读取并修改是行不通的,但微软官方帮我们封装了一下,看一下ActionExecutingContext 以及ActionContext:
在这里插入图片描述
在这里插入图片描述
ActionExecutingContext里面有一个ActionArguments,是一个字典,这就是http请求中的真实参数,而参数名称则在ActionContext.ActionDescriptor.Parameters中,所以就可以这么实现:

public class DESHandlerFilter : IActionFilter
    {
        public void OnActionExecuted(ActionExecutedContext context)
        {
            ObjectResult objectResult = context.Result as ObjectResult;
            WebApiResponse<string> apiResponse = objectResult.Value as WebApiResponse<string>;
            apiResponse.Data = Util.Core.DesHelper.EncryptDES(apiResponse.Data);
            objectResult.Value = apiResponse;
        }

        public void OnActionExecuting(ActionExecutingContext context)
        {
            var list = context.ActionDescriptor.Parameters;
            string obj = Util.Core.DesHelper.DecryptDES(context.ActionArguments[list[0].Name].ToString());
            context.ActionArguments[list[0].Name] = obj;
        }
    }

这里需要说明一下,因为是DES加密,所有的接口均只接受一个string参数,所以在上面的代码中可以context.ActionArguments[list[0].Name].ToString()来获取。如果有多个参数呢,微软官方提供了:自定义模型绑定。具体可以参考:https://docs.microsoft.com/zh-cn/aspnet/core/mvc/advanced/custom-model-binding?view=aspnetcore-5.0.
也可以参考这个链接中的做法:https://www.cnblogs.com/hyl8218/archive/2011/09/27/2192901.html.

最后别忘了在Startup中加上这句:

services.AddControllers(options => 
                    {
                        options.Filters.Add<DESHandlerFilter>();
                    });

结束

使用ActionFilter之后还有一个非常重大的惊喜,Swagger调试的时候再也不用先拿DES加密数据啦,只需要注释掉就跟正常的接口一样啦,实在是太方便了。

services.AddControllers(options => 
                    {
                        //options.Filters.Add<DESHandlerFilter>();
                    });
### 实现微信支付集成 为了在C# WinForms应用程序中实现微信支付功能,通常需要通过调用微信官方提供的API接口来完成支付流程。此过程涉及服务器端和客户端两部分的工作。 #### 服务端准备 首先,在服务器上部署一套能够处理来自微信支付平台请求的服务程序。该服务负责接收并解析来自微信的通知消息,验证签名合法性以及向微信发送响应数据包等操作。这部分工作一般采用PHP、Java或其他支持HTTPS协议的语言编写[^1]。 对于.NET环境下的开发者来说,可以考虑使用ASP.NET Core框架搭建RESTful Web API作为中间层,专门用于对接微信支付接口。具体步骤如下: - 注册成为微信开放平台开发者账号,并申请开通商户号; - 下载最新的微信支付SDK(推荐使用官方提供的NuGet包); - 编写控制器方法以接受前端传来的订单详情,并据此构造预付单请求提交给微信支付网关; ```csharp using Microsoft.AspNetCore.Mvc; using WeChatPaySharp; public class PayController : ControllerBase { private readonly IWechatPayClient _client; public PayController(IWechatPayClient client){ _client = client; } [HttpPost("/pay/unifiedorder")] public async Task<IActionResult> UnifiedOrder([FromBody] OrderModel order){ var response = await _client.UnifiedOrderAsync(new UnifiedOrderRequest{ Body = "商品描述", OutTradeNo = Guid.NewGuid().ToString(), TotalFee = (int)(order.TotalAmount * 100), // 单位转换成分为单位 SpbillCreateIp = Request.HttpContext.Connection.RemoteIpAddress.ToString(), NotifyUrl = "https://yourdomain.com/api/pay/notify" }); return Ok(response); } } ``` #### 客户端逻辑 当用户点击购买按钮时,WinForms应用应当发起HTTP POST请求至上述Web API获取prepay_id字段值,之后再利用这个id构建JSAPI支付所需的json对象传递给WebView控件加载的HTML页面中的JavaScript函数执行实际付款动作。由于WinForms本身并不具备直接展示网页的能力,因此这里建议引入第三方库如`cefsharp`来嵌入Chromium浏览器内核渲染H5页面[^2]。 下面给出一段简化版的示例代码片段展示了如何从本地项目启动CEF窗口并注入必要的js代码触发支付行为: ```csharp // Install-Package CefSharp.WinForms via Nuget Package Manager Console first. using CefSharp; using CefSharp.WinForms; private ChromiumWebBrowser browser; protected override void OnLoad(EventArgs e) { base.OnLoad(e); var settings = new CefSettings(); Cef.Initialize(settings); browser = new ChromiumWebBrowser("about:blank"); this.Controls.Add(browser); LoadPaymentPage(); } async void LoadPaymentPage(){ try{ using(var httpClient=new HttpClient()){ HttpResponseMessage resp=await httpClient.PostAsJsonAsync( $"http://{serverAddress}/api/pay/unifiedorder", new{total_amount}); if(resp.IsSuccessStatusCode){ dynamic data=JObject.Parse(await resp.Content.ReadAsStringAsync()); string prepayId=data.prepay_id; string jsCode=$@" function callWXPay(){{ WeixinJSBridge.invoke('getBrandWCPayRequest',{ 'appId':'{data.appId}', ... 'package' :'Sign={prepayId}' },function(res){{});}}; "; browser.LoadHtml($@"<html><body onload='callWXPay()'></body></html>"); browser.ExecuteScriptAsync(jsCode); } } }catch(Exception ex){} } ``` 需要注意的是以上仅为概念性的指导方案,实际开发过程中还需参照最新版本文档调整细节之处。另外考虑到安全性因素,务必妥善保管私钥文件并且严格按照规定设置回调地址白名单防止恶意篡改交易状态通知。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值