如何返回401响应和自定义页面?

时间:2013-08-30 16:19:00

标签: asp.net-mvc-4 .net-4.5 http-status-code-401

使用使用.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的答案,扩展了授权标签),但是如果没有已经描述过的类似错误,就无法完成任何工作。

有人可以帮忙吗?

1 个答案:

答案 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结果,以及我的自定义视图。