我正在构建的 ASP.NET MVC 网站有一个要求,即管理员需要能够在文件系统中手动创建一个 cshtml 文件(当然在 Views 文件夹下),然后能够访问该文件通过 Controller 操作进行翻页。 (即创建名为 Test.cshtml
的文件,然后通过 /Content/Test
访问)
我通过以下方法完成了此操作:
首先,自定义路由配置:
routes.MapRoute(
name: "StandardContent", // my controller
url: "Content/{pageName}",
defaults: new {controller = "Content", action = "Render", pageName = UrlParameter.Optional}
);
然后controller action以 View 名作为参数,检查请求的 View 名是否存在,然后渲染 View :
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 中写入的任何原始输入,并检查该输入是否存在 View 。用户是否可能写入一些恶意参数,从而允许他们访问通常应限制访问的文件(例如连接字符串文件)?如果是这样,我应该如何预防?
如果有帮助,这里是扩展方法 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;
}
确保在您的 View 文件名中只使用允许的符号(在我的例子中是字母、数字和下划线 (_))。
至于我,我将这个方法封装到 Controller 基类中:
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
继承了所有 Controller ,您就可以在任何需要的时候使用这个单行代码:
public ActionResult Render(string pageName)
{
return DynamicView(pageName); // short, simple and reusable
}
BaseController
是个很方便的东西,可以封装很多有用的 MVC 逻辑。
关于c# - 在 ASP.NET MVC 中动态呈现 View 的安全隐患,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43314539/