2017-04-10 77 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

美麗,漂亮,簡單,謝謝! :) –