绕过表单身份验证自动重定向到登录,如何?
-
09-06-2019 - |
题
我正在编写一个使用 asp.net-mvc 部署到 iis6 的应用程序。我正在使用表单身份验证。通常,当用户尝试在未经适当授权的情况下访问资源时,我希望他们被重定向到登录页面。FormsAuth 对我来说这件事很简单。
问题:现在我有一个由控制台应用程序访问的操作。让此操作响应状态 401 而不是将请求重定向到登录页面的最快方法是什么?
我希望控制台应用程序能够对此 401 StatusCode 做出反应,而不是透明的。我还想保留默认的将未经授权的请求重定向到登录页面的行为。
笔记:作为测试,我将其添加到我的 global.asax 中,它没有绕过表单身份验证:
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
HttpContext.Current.SkipAuthorization = true;
}
@戴尔和安迪
我正在使用 MVC 预览版 4 中提供的 AuthorizeAttributeFilter。这将返回 HttpUnauthorizedResult。此结果正确地将 statusCode 设置为 401。据我了解,问题在于 asp.net 正在拦截响应(因为其标记为 401)并重定向到登录页面,而不是仅仅让它通过。我想绕过某些网址的拦截。
解决方案
好的,我解决了这个问题。我制作了自定义 ActionResult (HttpForbiddenResult) 和自定义 ActionFilter (NoFallBackAuthorize)。
为了避免重定向,HttpForbiddenResult 使用状态代码 403 标记响应。FormsAuthentication 不会捕获此代码的响应,因此实际上会跳过登录重定向。NoFallBackAuthorize 过滤器检查用户是否已获得授权,与包含的 Authorize 过滤器非常相似。它的不同之处在于,当访问被拒绝时,它返回 HttpForbiddenResult。
HttpForbiddenResult 非常简单:
public class HttpForbiddenResult : ActionResult { public override void ExecuteResult(ControllerContext context) { if (context == null) { throw new ArgumentNullException("context"); } context.HttpContext.Response.StatusCode = 0x193; // 403 } }
似乎无法跳过 FormsAuthenticationModule 中的登录页面重定向。
其他提示
可能是一个拼凑(甚至可能不起作用),但在您的登录页面上看看是否 Request.QueryString["ReturnUrl"] != null
如果这样设置 Response.StatusCode = 401
.
请记住,您仍然需要让控制台应用程序以某种方式进行身份验证。您无法免费获得 HTTP 基本身份验证:你必须自己动手,但有很多实现。
您是否为该操作编写了自己的 FormsAuth 属性?如果是这样,在 OnActionExecuting 方法中,您将获得 FilterExecutingContext 的传递。您可以使用它来传回 401 代码。
public class FormsAuth : ActionFilterAttribute
{
public override void OnActionExecuting(FilterExecutingContext filterContext)
{
filterContext.HttpContext.Response.StatusCode = 401;
filterContext.Cancel = true;
}
}
这应该有效。我不确定您是否编写了 FormsAuth 属性,或者是否从其他地方获得了它。
我还没有使用过 Preview 4 中的 AuthorizeAttribute。我自己推出了,因为自从第一个 CTP 以来我一直在使用 MVC 框架。我快速查看了 Reflector 中的属性,它在内部执行了我上面提到的操作,只不过它们使用了 401 的十六进制等效值。我需要进一步查找调用,以查看捕获异常的位置,因为这很可能是他们进行重定向的位置。这是您需要覆盖的功能。我不确定你是否能做到这一点,但当我找到它时我会发回来并给你一个解决方案,除非 Haacked 看到这个并自己发布。
我做了一些谷歌搜索,这就是我想到的:
HttpContext.Current.Response.StatusCode = 401;
不确定它是否有效,我没有测试过。不管怎样,都值得一试,对吧?:)