简体   繁体   English

ASP.NET MVC-验证路由的存在

[英]ASP.NET MVC - Verify the Existence of a Route

My ASP.NET MVC application has a scenario where user input can directly influence the target of a call to RedirectToAction() (by way of a string) and there is a chance that the user could create a run-time error if improper input leads them to request an action that does not exist. 我的ASP.NET MVC应用程序有一个场景,其中用户输入可以直接影响对RedirectToAction()的调用目标(通过字符串),并且如果输入不正确导致用户有可能创建运行时错误。他们请求不存在的操作。 I'd like to prevent this problem outright, but I'd like to do so in the least taxing way possible as it must be done on a large number of requests. 我想彻底避免此问题,但我想以最省力的方式做到这一点,因为必须对大量请求进行处理。 That being said, reflection would be a viable solution to use to confirm that /Controller/ActionName actually exists, but reflection is a pretty heavy operation. 话虽如此,反射将是一个可行的解决方案,用于确认/ Controller / ActionName实际上存在,但是反射是一项非常繁重的操作。

What would be the best way to confirm that a given Url in an ASP.NET MVC application is in fact wired to a controller action? 确认ASP.NET MVC应用程序中的给定URL实际上与控制器操作关联的最佳方法是什么?

One way to do it would be to have a list of allowable values for the user inputted data. 一种方法是拥有用户输入数据的允许值列表。 For example, if the user inputted her favourite colour: 例如,如果用户输入了她喜欢的颜色:

// userColour = the user set colour
var allowableColours = new [] { "Red", "Blue", "Green" };
if (!allowableColours.Contains(userColour))
{
    // Set to a default colour.
    userColour = "Red";
}

return RedirectToAction(userColour, "Colour");

Although not as dynamic as looking at the routing table, it would be fast and you could be confident they the user wasn't inputting some malicious value that was screwing with your routing. 尽管它不像查看路由表那样动态,但它很快,并且您可以确信他们没有输入一些恶意的值来破坏您的路由。

A quick and more crude option is to just hit the url, the following code may help you quickly test something, 一种快速而粗略的选择是直接点击网址,以下代码可以帮助您快速进行测试,

Note: you're actually hitting your site and be aware of what that means in your application. 注意:您实际上是在访问您的网站,并意识到这在您的应用程序中意味着什么。

This was helpful for us diagnosing some environment issues in some integration tests. 这有助于我们在某些集成测试中诊断一些环境问题。

var urlToExec = "http://yoursite.com/" + controllerAndAction;

var wr = (HttpWebRequest) WebRequest.Create(urlToExec);

try
{
    var resp = (HttpWebResponse)wr.GetResponse();

    if (resp.StatusCode != HttpStatusCode.OK || resp.StatusCode == HttpStatusCode.NotFound)
        //it was found

}
catch (Exception ex)
{
    //404 or other http error
    //404 and the like result in GetResponse() throwing an exception
    //this was verified by having actions return via:
    //'return new HttpNotFoundResult("This doesn't exist");'
}

The route I ended up taking here was reflection and a Dictionary containing all of the valid actions in the relevant Controller which is stored in Application[]. 我最终在这里采取的路线是反射和包含在Application []中存储的相关Controller中所有有效动作的Dictionary(字典)。 A valid Action is determined by checking the method's ReturnType and verifying that it is (or derives from) ActionResult and that it is not Private. 通过检查方法的ReturnType并确认它是ActionResult(或从ActionResult派生)并且它不是Private,可以确定有效的Action。 I could do some more checks, but these are sufficient for now. 我可以再做一些检查,但是现在这些已经足够了。

public static bool MethodIsAction(MethodInfo method)
{
    if (method == null)
        throw new ArgumentNullException("Invalid Parameter: method cannot be null.");

    if (method.ReturnType != typeof(ActionResult) && method.ReturnType.BaseType != typeof(ActionResult))
        return false;

    if (method.IsPrivate)
        return false;

    return true;
}

The dictionary of actions is built with the following method inside Application_Start: 动作字典是通过Application_Start中的以下方法构建的:

public static Dictionary<string, MethodInfo> GetActionDictionary(Type controller)
{
    Dictionary<string, MethodInfo> dict = null;

    var methods = controller.GetMethods().Where(MethodIsAction);
    if (methods.Any())
    {
        dict = new Dictionary<string, MethodInfo>(StringComparer.OrdinalIgnoreCase);
        foreach (var action in methods)
            dict.Add(action.Name, action);
    }
    return dict;
}

When a user requests a qualifying action I simply point the action name at the Dictionary and if a MethodInfo exists for that action name I invoke it. 当用户请求限定动作时,我只需将动作名称指向“字典”即可,如果该动作名称存在MethodInfo,则将其调用。 While it still requires reflection, it's at least optimized so that it only ever happens once while the application is running. 尽管它仍然需要反射,但至少已对其进行了优化,以使其仅在应用程序运行时发生一次。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM