C#ASP.NET MVC 5 - > ActionFilterAttribute - >停止自动重定向HTTP 401

时间:2018-01-25 15:04:35

标签: c# asp.net asp.net-mvc asp.net-mvc-5

我将以下System.Web.Mvc.ActionFilterAttribute注册为全局过滤器。如果响应为400 BadRequest,则应用程序按预期工作但如果我返回401 Unauthorized,我得到的是302 Found重定向。

由于Login?ReturnUrl=将继续追加值,因此请求将抛出一个查询字符串太长的异常。

  

HTTP错误404.15 - 未找到

     

请求过滤模块是   配置为拒绝查询字符串太长的请求。

https://localhost:44311/Login?ReturnUrl=%2FLogin%3FReturnUrl%3D%252FLogin%253FReturnUrl%253D%25252FLogin%25253FReturnUrl%25253D%2525252FLogin% ....

enter image description here

Web.config我已停用defaultRedirect并将customErrors设为<customErrors mode="Off" />

public class ClientCertificateActionFilter : System.Web.Mvc.ActionFilterAttribute
{
  public override void OnActionExecuting(System.Web.Mvc.ActionExecutingContext actionContext)
  {
    if (actionContext.HttpContext.Request.Url.Scheme != Uri.UriSchemeHttps)
    {
      actionContext.Result = new HttpStatusCodeResult(HttpStatusCode.BadRequest, "HTTPS Required");
      return;

    }
    else
    {
      X509Certificate2 cert = new X509Certificate2(actionContext.HttpContext.Request.ClientCertificate.Certificate);

      if (cert == null)
      {
        actionContext.Result = new HttpStatusCodeResult(HttpStatusCode.Unauthorized, "Client Certificate Required");
        return;
      }
      ...
    }
  }
}

我该如何解决这个问题?

3 个答案:

答案 0 :(得分:1)

您正在返回HttpStatusCode.Unauthorized,这会导致重定向到登录页面。因为过滤器每次都在执行,所以它在到达后会保持重定向到自身。

你应该返回的是403(HttpStatusCode.Forbidden)。

答案 1 :(得分:1)

问题是你正在扩展MVC的错误部分。 MVC有一个AuthorizeAttribute,它是一个IAuthorizationFilter,你可以扩展它来放置这样的自定义功能。 MVC使用HTTP 401作为特殊状态,指示重定向到登录页面,这是从默认AuthorizeAttribute返回的内容(据我所知,无法更改)这要使用不同的状态代码)。

您找到的“解决方案”here仅禁用重定向(不仅针对您的特殊情况,还针对AuthorizeAttribute),因此当有人尝试访问不允许的网页时,他们会获取HTTP 401响应,而不是重定向到登录页面(正如大多数用户所期望的那样)。

您应该执行的操作是将此额外检查添加到AuthorizeAttribute的子类,然后使用自定义授权属性代替AuthorizeAttribute,而不是使用操作过滤器。然后,您可以保留登录页面,它将按预期重定向。

public class CustomAuthorize : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        X509Certificate2 cert = new X509Certificate2(httpContext.Request.ClientCertificate.Certificate);

        if (cert == null)
        {
            return false;
        }

        return base.AuthorizeCore(httpContext);
    }
}

如果您坚持使此案例与正常的“重定向(如果未授权”)行为不同,则对于无效证书的情况,您应使用与HTTP 401不同的状态代码,以便ASP.NET不会劫持响应并转向它变成了302。

答案 2 :(得分:0)

<强>更新

我首先编辑了我的过滤器,并将AuthorizeAttributeAuthorizeCore一起使用。我编辑的原因是当我尝试了一些未被捕获的异常时。在这种情况下,除非我捕获异常并返回HttpStatusCode.Unauthorized或类似内容,否则将对用户进行身份验证。但是我不得不还原我更改的代码。原因是使用[AllowAnonymous]声明的控制器或方法没有命中代码。该应用程序甚至需要有效的客户端证书才能查看登录页面,因此我不会回到ActionFilterAttribute

<强>原始

查看响应标头我可以看到响应包含标头www-authenticate: Bearer

然后我不去文件App_Start - &gt; Startup.Auth.cs查看身份验证。在OAuthAuthorizationServerOptionsOAuthBearerAuthenticationOptions我没有看到任何奇怪的内容。但是,该应用程序也启用了app.UseCookieAuthentication。在此处,CookieAuthenticationOptions设置为LoginPath = new PathString("/Login"),。这是导致重定向的原因。

LoginPath的说明:

  

LoginPath属性通知中间件它应该更改   传出401未授权状态码到302重定向到   给定登录路径。生成401的当前url被添加到   LoginPath作为查询字符串参数   ReturnUrlParameter。一旦对LoginPath的请求授予新的   SignIn标识,ReturnUrlParameter值用于重定向   浏览器返回到导致原始未授权状态的URL   码。如果LoginPath为null或为空,则中间件将不会显示   对于401 Unauthorized状态代码,它不会重定向   登录发生时自动。

删除此参数后,一切正常。

enter image description here