在ASP.NET MVC动态呈现视图中的安全隐含
问题描述:
我正在构建ASP.NET MVC网站,要求管理员需要能够在文件系统中手动创建cshtml文件(在Views当然文件夹),然后能够通过控制器操作访问该页面。 (即创建文件名为Test.cshtml
,然后通过/Content/Test
访问)在ASP.NET MVC动态呈现视图中的安全隐含
我通过以下方式做到了这一点:
首先,自定义路由配置:
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;
}
确保(在我的大小写字母,数字和下划线(_))在您的视图文件名使用只允许符号。
至于我,我incapsulated这种方法为基础的控制器类:
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逻辑。
美丽,漂亮,简单,谢谢! :) –