使用RouteExistingFiles属性限制对文件夹的访问

来源:互联网 发布:李兴华java视频教程 编辑:程序博客网 时间:2024/06/13 05:57

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
publicstaticvoid 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
publicstaticvoid 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
publicclassPhotoController : 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
publicclassPhotoAuthorizeAttribute : AuthorizeAttribute
{
    protectedoverridebool 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
publicstaticvoid 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");
}


0 0
原创粉丝点击