繁体   English   中英

在ASP.NET MVC中动态呈现视图的安全隐患

[英]Security implications in dynamically rendering views in ASP.NET MVC

我正在构建的ASP.NET MVC网站有一个要求,即管理员需要能够在文件系统中手动创建cshtml文件(当然在Views文件夹下),然后才能通过控制器动作。 (即创建名为Test.cshtml文件,然后通过/Content/Test访问)

我通过以下方法完成了这项工作:

首先,自定义路由配置:

routes.MapRoute(
            name: "StandardContent", // my controller
            url: "Content/{pageName}",
            defaults: new {controller = "Content", action = "Render", pageName = UrlParameter.Optional}
        );

然后将视图名称作为参数的控制器操作检查所请求的视图名称是否存在然后呈现视图:

public ActionResult Render(string pageName)
{
    if (pageName.IsNullOrEmpty())
    {
        return RedirectToAction("Index", "Home");
    }

    // if no view exists with this name, go 404
    if (!this.ViewExists(pageName)) // my extension method for view checking
    {
        return RedirectToAction("NotFound", "Error");
    }

    return View(pageName);
}

这非常有效,我很满意,除了它的安全隐患。 在这里,我基本上采用用户在url中写入的任何原始输入 ,并检查该输入是否存在视图。 用户是否可能编写一些恶意参数 ,这些参数可能允许他们访问通常应限制访问的文件(例如连接字符串文件)? 如果是这样,我该如何预防呢?


这是扩展方法this.ViewExists(pageName)的代码,如果有帮助的话。

public static bool ViewExists(this Controller controller, string viewName)
{
    var result = ViewEngines.Engines.FindView(controller.ControllerContext, viewName, null);
    return result.View != null;
}

我在我的应用程序中具有相同的功能,只需添加正则表达式检查以更好地睡眠。
您只需将其添加到ViewExists方法即可:

public static bool ViewExists(this Controller controller, string viewName)
{
    // check for viewName null or empty here?

    if (!Regex.IsMatch(viewName, "^[A-Za-z0-9_]+$"))
        throw new HttpException(404, "Not found");

    var result = ViewEngines.Engines.FindView(controller.ControllerContext, viewName, null);
    return result.View != null;
}

确保在视图文件名中仅使用允许的符号(在我的例子中为字母,数字和下划线(_))。


至于我,我把这个方法封装到基类控制器类中:

public class BaseController : Controller 
{
    public ActionResult DynamicView(string viewName)
    {
        if (string.IsNullOrWhiteSpace(pageName))
            return RedirectToAction("Index", "Home");

        if (!Regex.IsMatch(viewName, "^[A-Za-z0-9_]+$"))
            return RedirectToAction("NotFound", "Error");

        var result = ViewEngines.Engines.FindView(ControllerContext, viewName, null);
        if (result.View == null)
            return RedirectToAction("NotFound", "Error");

        return View(viewName);
    }
}

然后,如果您从此BaseController继承所有控制器,则可以在需要时使用此单行程序:

public ActionResult Render(string pageName)
{
    return DynamicView(pageName); // short, simple and reusable
}

BaseController一般是方便的东西,可以包含许多有用的MVC逻辑。

暂无
暂无

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

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