使用RouteExistingFiles屬性限制對文件夾的訪問

RouteExistingFiles 屬性

          當用戶請求如圖片、視頻等靜態文件資源時,asp.net會很高興的定位文件位置並提供給用戶,除非我們做了某些限制。有時我們需要做一些限制只能讓所有者訪問而不能讓其他用戶訪問,一種簡單的情況是通過web.config 文件配置進行限制,但在複雜的情況下,如果能夠通過action/filter控制訪問權限將是不錯的選擇,爲了實現這個目的需要將靜態文件請求通過MVC pipeline 進行處理,而MVC的RouteExistingFiles屬性恰好能做到,通過將RouteExistingFiles屬性設置爲true,MVC將處理這些請求,而不是由iis處理這些靜態文件請求。

      下面討論如何實現,例如:

下面是 Global.asax.cs文件

1
2
3
4
5
6
7
8
9
10
publicstatic void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
 
    routes.MapRoute(
        "Default",
        "{controller}/{action}/{id}",
        new{ controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
}

設置RouteExistingFiles = true,禁止 IIS 處理這些存在的靜態文件請求併發送結果

1
2
3
4
5
6
7
publicstatic void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
 
    routes.RouteExistingFiles = true;
    ...
}

下一步,需要定義一個新的路由處理這些情況,URL模式部分看起來比較象物理路徑,但不用如此,這裏只是個例子.

1
2
3
4
5
routes.MapRoute(
    "photo",
    "premium/photos/{accountNo}/{image}",
    new{ controller = "Photo", action = "Index"}
);

如你所想,我們需要新建controller和action ,index方法將返回請求的完整路徑.

1
2
3
4
5
6
7
publicclass PhotoController : Controller
{
    publicFileResult Index()
    {
        returnFile(Request.RawUrl, "image/jpeg");
    }
}

但我們的index方法仍然不安全,需要添加驗證,通過自定義authorize 屬性 ,這個自定義屬性通過檢查url中的accountNo 和存在session的accountNo作對比,如果不匹配,則返回401

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
publicclass PhotoAuthorizeAttribute : AuthorizeAttribute
{
    protectedoverride bool AuthorizeCore(HttpContextBase httpContext)
    {
        if(base.AuthorizeCore(httpContext))
        {
            var accountNo = httpContext.Request.RequestContext.RouteData.Values["accountNo"];
 
            if(accountNo != null&& httpContext.Session["AccountNo"].ToString() == accountNo.ToString())
            {
                returntrue;
            }
 
            returnfalse;
        }
 
        returnfalse;
    }
}

我們需要給返回靜態文件資源的action加上自定義權限驗證屬性PhotoAuthorize attribute.

1
2
3
4
5
[PhotoAuthorize]
publicFileResult Index()
{
    returnFile(Request.RawUrl, "image/jpeg");
}

但有一個重要的問題是,一旦把RouteExistingFiles屬性設置爲true,Content文件夾下的styles 和 javascript 的文文件同樣會被阻止,這是個大問題,這個屬性的影響是全局的,那如何發送這些css, js文件?爲它們單獨創建controller和action是個不好的方法,幸運的是還有IgnoreRoutemethod方法可以方便解決這個問題

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
publicstatic void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
 
    routes.IgnoreRoute("Content/{*relpath}");
 
    routes.RouteExistingFiles = true;
 
    routes.MapRoute(
        "photo",
        "premium/photos/{accountNo}/{image}",
        new{ controller = "Photo", action = "Index"}
    );
 
    routes.MapRoute(
        "Default",
        "{controller}/{action}/{id}",
        new{ controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
}

IgnoreRoute 告訴路由模塊 routing module 不要處理這些請求,請注意:需要在RouteExistingFiles=true之前調用ignoreroute方法。.

避免客戶端緩存

最後一個問題就是瀏覽器緩存。瀏覽器會緩存圖片,未授權用戶能夠看到這些緩存的受限圖片,通過 OutputCache attribute告訴瀏覽器不要緩存這些圖片即可

1
2
3
4
5
6
[PhotoAuthorize]
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "None")]
publicFileResult Index()
{
    returnFile(Request.RawUrl, "image/jpeg");
}


發佈了62 篇原創文章 · 獲贊 6 · 訪問量 49萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章