2017-04-10 36 views
2

我正在构建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; 
} 

回答

2

我在我的应用程序中具有相同的功能,只是简单地添加了正则表达式检查以更好地睡眠。
你可以简单地把它添加到您的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逻辑。

+0

美丽,漂亮,简单,谢谢! :) –

相关问题