Twilio RequestValidation示例的ActionFilterAttribute不起作用-原因



首先,我是MVC的新手,所以请耐心等待。我遵循这里的Twilio示例来验证来自Twilio的状态回调是否真实:https://www.twilio.com/docs/usage/tutorials/how-to-secure-your-csharp-aspnet-app-by-validating-incoming-twilio-requests#create-a-自定义过滤器-属性

Twilio应该审查按原样提供的代码,因为构造函数名称中有一个拼写错误;RequestAttribute";两次。

我的问题是,当我把属性放在控制器上时,我一辈子都无法解决它。我注意到示例Action Filter有一个以"结尾的名称空间;。过滤器";并且我注意到我的MVC应用程序没有";过滤器";目录一些谷歌搜索表明,MVC4和5之间可能存在差异——根据我所知,我正在使用MVC5,因为这是系统上列出的版本号。网状物Mvc参考(5.2.2.0版,如果有重要内容,请特别说明)。

无论如何,Twilio在这里链接到了关于创建自定义操作筛选器的Microsoft文档:https://learn.microsoft.com/en-us/previous-versions/aspnet/dd410056(v=vs.98)?重定向自=MSDN

微软建议直接在";控制器";目录——所以我把我的放在那里。以下是该类当前的读取方式:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Twilio.Security;
using System.Net;
using System.Web.Mvc;
using System.Web.Mvc.Filters;

namespace SMSStatusWS.Controllers
{
public class ValidateTwilioRequestAttribute : System.Web.Mvc.ActionFilterAttribute
{
private readonly RequestValidator _requestValidator;
public ValidateTwilioRequestAttribute()
{
var authToken = "<--------REMOVED------->";
_requestValidator = new Twilio.Security.RequestValidator(authToken);
}
public override void OnActionExecuting(ActionExecutingContext actionContext)
{
var context = actionContext.HttpContext;
if (!IsValidRequest(context.Request))
{
actionContext.Result = new HttpStatusCodeResult(HttpStatusCode.Forbidden);
}
base.OnActionExecuting(actionContext);
}
private bool IsValidRequest(HttpRequestBase request)
{
var signature = request.Headers["X-Twilio-Signature"];
var requestUrl = request.Url.AbsoluteUri;
return _requestValidator.Validate(requestUrl, request.Form, signature);
}
}
}

然后我尝试使用它…

[HttpPost]
[ValidateTwilioRequest ]
public ActionResult UpdateSmsStatus(string dbContext, string smsQueueId)
{
// Controller code here...
}

属性[ValidateTwilioRequest ]在Visual Studio中高亮显示为红色。。。这意味着它无法解决它(我想),但我不确定为什么,因为我的控制器类和操作过滤器类中的命名空间都是相同的。。。

namespace SMSStatusWS.Controllers

所以在这一点上,我不确定这里出了什么问题。据我所知,自定义动作过滤器是正确创建的,正如Twilio所示,我正在使用它,但它不起作用。即使过滤器似乎没有解析,项目也会构建并运行。。。但当然,它永远不会碰到动作过滤器中的代码。

是否有其他方式需要引用文档没有告诉我的操作过滤器?思考我可能忽略了该尝试或寻找什么?

更新10/13/21:我已经取得了一些进展。。。发现未解析的属性与Visual Studio有关。由于无法弄清楚它没有解析的原因,我关闭了解决方案并重新启动了Visual Studio,当我重新打开它时,它立即开始解析属性。然而,我不确定它是否有效,因为我无法在OnActionExecuting覆盖中找到断点,而且Visual Studio说没有加载任何符号。

所以现在的新问题是,如何调试自定义操作过滤器?难道我不应该使用调试器进入代码吗?

您可以尝试使用System。诊断。调试。OnActionExecuting函数中的WriteLine,并使用它而不是断点。这应该写入输出窗口,并让您知道该代码是否正在运行。添加该代码后,您的OnActionExecuting函数将如下所示。

public override void OnActionExecuting(ActionExecutingContext actionContext)
{
string controller = actionContext.ActionDescriptor.ControllerDescriptor.ControllerName;
string action = actionContext.ActionDescriptor.ActionName;
System.Diagnostics.Debug.WriteLine("Controller-" + controller + ", Action-" + action);
var context = actionContext.HttpContext;
if (!IsValidRequest(context.Request))
{
actionContext.Result = new HttpStatusCodeResult(HttpStatusCode.Forbidden);
}
base.OnActionExecuting(actionContext);
}

哇。。。今天学习了一些有关Visual Studio和调试的知识。我为所有这些创建的MVC项目将项目输出设置为比我的项目高2级的bin目录。我称之为";全局bin"-我们使用我们的全局bin作为许多其他项目写入输出的地方,并且在我们的夜间构建中引用了一个位置。

我注意到,我的本地项目bin目录中有一个旧的DLL和PDB文件,可能是在将输出目录更改为全局bin之前的构建中(全局bin有当前的DLL和PDB)。在调试时,我会注意到调试器会从";"临时Asp.Net文件";路径(在Visual Studio中调试时,您可以在"模块"窗口中找到这些信息)-这个临时目录中有相同的旧版本的pdb,这就是我最终无法调试我的操作筛选器属性的原因-它有一个过时的pdb,其中没有我最新代码更改的符号。

目前,我的创可贴是将我的项目的输出目录设置回它自己的本地bin目录,并在web.config中禁用shadowCopyBinAssemblies,这可以防止调试器使用Temporary Asp.Net files目录中过时的pdb,而是使用本地bin中的pdb。

在web.config…中看起来是这样的

<system.web>
<hostingEnvironment shadowCopyBinAssemblies="false"/>
<system.web

我很困惑Visual Studio为什么不将dll和pdb从我们定义的全局bin(当它被定义为项目的输出目录时)阴影复制到Temporary Asp.Net文件目录。这将解决所有这些问题,但我不知道是否可以在任何地方进行配置

一旦我将其更改为输出到项目的bin目录并在web.config中禁用shadowCopy,调试器就会从正确的dll和pdb加载符号,我的断点就会立即命中。

我想我会添加一个构建后事件或其他东西来复制dll&pdb文件到我们的全局bin,所以这不会破坏我们的夜间构建,但这感觉像是一次黑客攻击。如果Temporary Asp.Net Files目录的默认shadowCopy设置无法更改,我不知道该怎么办。这可能是Visual Studio的错误吗。。。shadow始终从项目bin复制,即使输出被配置为写入其他地方?

最新更新