【发布时间】:2022-12-01 15:53:42
【问题描述】:
我的一些动作接受以下模型:
public class PaymentRequest
{
public decimal Amount { get; set; }
public bool? SaveCard { get; set; }
public int? SmsCode { get; set; }
public BankCardDetails Card { get; set; }
}
public class BankCardDetails
{
public string Number { get; set; }
public string HolderName { get; set; }
public string ExpiryDate { get; set; }
public string ValidationCode { get; set; }
}
动作方法如下所示:
[HttpPost]
[Route("api/v1/payment/pay")]
public Task<BankCardActionResponse> Pay([FromBody] PaymentRequest request)
{
if (request == null)
throw new HttpResponseException(HttpStatusCode.BadRequest);
return _paymentService.PayAsync(DataUserHelper.PhoneNumber, request);
}
我使用 Nlog。我认为记录所有这些银行数据显然不是一个好主意。我的日志配置文件包含以下行:
<attribute name="user-requestBody" layout="${aspnet-request-posted-body}"/>
我记录了请求。我决定重构它并计划以下策略。在他们的请求中包含敏感数据的操作我将用类似的属性标记
[RequestMethodFormatter(typeof(PaymentRequest))]
然后看看我的自定义渲染器:
[LayoutRenderer("http-request")]
public class NLogHttpRequestLayoutRenderer : AspNetRequestPostedBody
{
protected override void DoAppend(StringBuilder builder, LogEventInfo logEvent)
{
base.DoAppend(builder, logEvent);
var body = builder.ToString();
// Get attribute of the called action.
var type = ... // How can I get "PaymentRequest" from the [RequestMethodFormatter(typeof(PaymentRequest))]
var res = MaskHelper.GetMaskedJsonString(body, type);
// ... and so on
}
}
我想你明白这个想法。我需要方法的 RequestMethodFormatter 属性中的类型。甚至有可能将它放入渲染器中吗?我需要它,因为我要将请求 JSON 反序列化为特定模型(它将进入 MaskHelper.GetMaskedJsonString),使用屏蔽数据的模型,将其序列化回 JSON。
那么,我是否选择了错误的方法?或者可以从属性中获取类型到渲染器中?
【问题讨论】:
-
如果你想记录银行数据,我不建议这样做,那么至少要疯狂地加密它,或者用一种疯狂的单向密码将它包装起来。显然,后者带来的问题是您无法重新创建数据,只能确认它是您所拥有的,是您的密码验证它的内容。但理论上,您可以做很多事情。如果你想把你所说的“屏蔽”设为可选,我只想说,创建一个工厂/策略模式,并根据你提供的参数,创建一个屏蔽或不屏蔽数据的类,发送到日志。
-
您可以通过使用装饰器进一步使其整洁,因此屏蔽被称为记录方法的装饰,然后仅在通过策略模式找到策略时应用。这将使它成为一个非常干净的实现,并且易于测试。或者,您可以采用面向方面的编程方式,在调用某些方法时编织掩码。
-
请注意 NLog.Web 存储库已开放请求请求以改进
${aspnet-request-posted-body}的中间件,因此您可以在中间件中进行清理/屏蔽,而不是使用自定义布局渲染器。
标签: c# .net asp.net-mvc nlog .net-4.8