使用使用.NET 4.5和IIS 8的MVC4应用程序。当权限检查失败时,是否有办法返回自定义的未授权页面和401结果?
我也在使用表单身份验证,并希望在用户未登录时重定向到登录页面,但是当用户没有有效权限(即管理员)时重定向到未授权页面。
我还必须小心重定向,然后在成功重定向时获得200/301结果。
我需要返回401状态代码并保留在当前页面上,同时还返回自定义的未经授权的页面。
我有一个错误控制器,它返回一个未经授权的视图:
[ActionName("unauthorised")]
public ActionResult Http401() {
Response.StatusCode = 401;
Response.StatusDescription = "Unauthorised";
Response.SuppressFormsAuthenticationRedirect = true;
return View("unauthorised");
}
如果检查权限失败,我有一些方法可以尝试调用401:
/// <summary>Method to invoke when user attempts action without relevant permission</summary>
/// <param name="httpContext">the httpcontext</param>
/// <returns>empty result</returns>
public ActionResult InvokeHttp401(HttpContextBase httpContext) {
Transfer("/error/unauthorised");
return new EmptyResult();
}
private void Transfer(string url) {
var uriBuilder = new UriBuilder(Request.Url.Scheme, Request.Url.Host, Request.Url.Port, Request.ApplicationPath); // Create URI builder
uriBuilder.Path += url; // Add destination URI
string path = Server.UrlDecode(uriBuilder.Uri.PathAndQuery); // Because UriBuilder escapes URI decode before passing as an argument
this.HttpContext.RewritePath(path, false); // Rewrite path
HttpContext.Server.TransferRequest(path, true);
}
注意:我正在使用Server.TransferRequest,以便我可以尝试在当前网址上返回401结果,而不会导致任何重定向。我正在检查常规ActionResult中的权限,如下所示:
[Authorize]
public ActionResult MyMethod() {
if (!UserHasPermission(Admin))
return InvokeHttp401(HttpContext);
......
如果用户未登录,authorize标记将重定向到登录,则会进行其他权限检查。
通过上面的设置,我可以返回401结果并保留当前网址,但显示的是IIS 401错误,而不是当前页面。
我还试图在我的web.config文件中设置以下内容:
<httpErrors errorMode="DetailedLocalOnly" existingResponse="Replace">
.....
<error statusCode="401" responseMode="ExecuteURL" path="/Error/unauthorised" />
</httpErrors>
但这没有区别。如果我没有在我的Http401 ActionResult中设置状态代码,我可以获得自定义的未经授权的页面,但它只返回200结果。
我查看了question上的帖子(特别是Timothy的答案,扩展了授权标签),但是如果没有已经描述过的类似错误,就无法完成任何工作。
有人可以帮忙吗?
答案 0 :(得分:3)
终于搞清楚了 -
使用Timothy在链接问题和blog post中建议的自定义授权标记的组合,我可以暂时将状态代码设置为418,然后在Global中将其更改回401。 END_REQUEST。
我要做的最后一件事是在我的web.config中添加418并使用PassThrough
模式:
<httpErrors errorMode="DetailedLocalOnly" existingResponse="PassThrough">
<remove statusCode="404" />
<error statusCode="404" responseMode="ExecuteURL" path="/Error/not-found" />
<remove statusCode="500" />
<error statusCode="500" responseMode="ExecuteURL" path="/Error/error" />
<remove statusCode="401" />
<error statusCode="401" responseMode="ExecuteURL" path="/Error/unauthorised" />
</httpErrors>
我在同一个网址上获得了401结果,以及我的自定义视图。