下面是 Global.asax.cs文件
1
2
3
4
5
6
7
8
9
10
|
public
static
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
|
public
static
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
|
public
class
PhotoController : Controller
{
public
FileResult Index()
{
return
File(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
|
public
class
PhotoAuthorizeAttribute : AuthorizeAttribute
{
protected
override
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())
{
return
true
;
}
return
false
;
}
return
false
;
}
}
|
我们需要给返回静态文件资源的action加上自定义权限验证属性PhotoAuthorize attribute.
1
2
3
4
5
|
[PhotoAuthorize]
public
FileResult Index()
{
return
File(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
|
public
static
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"
)]
public
FileResult Index()
{
return
File(Request.RawUrl,
"image/jpeg"
);
}
|