我将以下System.Web.Mvc.ActionFilterAttribute
注册为全局过滤器。如果响应为400 BadRequest
,则应用程序按预期工作但如果我返回401 Unauthorized
,我得到的是302 Found
重定向。
由于Login?ReturnUrl=
将继续追加值,因此请求将抛出一个查询字符串太长的异常。
HTTP错误404.15 - 未找到
请求过滤模块是 配置为拒绝查询字符串太长的请求。
在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;
}
...
}
}
}
我该如何解决这个问题?
答案 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)
<强>更新强>
我首先编辑了我的过滤器,并将AuthorizeAttribute
与AuthorizeCore
一起使用。我编辑的原因是当我尝试了一些未被捕获的异常时。在这种情况下,除非我捕获异常并返回HttpStatusCode.Unauthorized
或类似内容,否则将对用户进行身份验证。但是我不得不还原我更改的代码。原因是使用[AllowAnonymous]
声明的控制器或方法没有命中代码。该应用程序甚至需要有效的客户端证书才能查看登录页面,因此我不会回到ActionFilterAttribute
。
<强>原始强>
查看响应标头我可以看到响应包含标头www-authenticate: Bearer
。
然后我不去文件App_Start
- &gt; Startup.Auth.cs
查看身份验证。在OAuthAuthorizationServerOptions
和OAuthBearerAuthenticationOptions
我没有看到任何奇怪的内容。但是,该应用程序也启用了app.UseCookieAuthentication
。在此处,CookieAuthenticationOptions
设置为LoginPath = new PathString("/Login"),
。这是导致重定向的原因。
LoginPath
的说明:
LoginPath属性通知中间件它应该更改 传出401未授权状态码到302重定向到 给定登录路径。生成401的当前url被添加到 LoginPath作为查询字符串参数 ReturnUrlParameter。一旦对LoginPath的请求授予新的 SignIn标识,ReturnUrlParameter值用于重定向 浏览器返回到导致原始未授权状态的URL 码。如果LoginPath为null或为空,则中间件将不会显示 对于401 Unauthorized状态代码,它不会重定向 登录发生时自动。
删除此参数后,一切正常。