如何在不重定向到LogIn视图的情况下返回未授权的代码

时间:2010-09-10 19:11:22

标签: json asp.net-mvc-2 rest

我的MVC Web应用程序提供两种类型的用户。

  • 首先通过标准网络浏览器;
  • 第二个通过REST返回仅返回JSON数据。

此外,

  • 两者都需要身份验证和授权;
  • 根据路线区分两种方案,以便了解要提供的内容。

当用户访问应用程序时,如果他们未登录,则应用程序的反应应该不同。

  1. 在第一种情况下,它应该返回默认的LogIn页面(这很好)。
  2. 在第二种情况下,它应该仅返回401 Unauthorized代码。
  3. 我习惯使用WCF REST服务,在那里我可以引发这样的异常:

    throw new WebProtocolException(System.Net.HttpStatusCode.Unauthorized, exc.Message, exc);
    

    并收到401消息。当我把statusCode放在这样的时候,在MVC中使用相同方法的问题:

    HttpContext.Response.StatusCode = (Int32)HttpStatusCode.Unauthorized
    

    它总是重定向到LogIn页面。

    我该怎么做?

    我尝试覆盖AuthorizeAttribute并处理OnAuthorization函数,但是一旦我将statusCode设置为401,它就会被重定向到LogIn页面。

6 个答案:

答案 0 :(得分:25)

要防止登录页面重定向,您必须将SuppressFormsAuthenticationRedirect的{​​{1}}属性设置为true;

HttpContext.Response

答案 1 :(得分:3)

您遇到的是ASP.NET MVC中的漏洞(我希望有一天能解决这个问题)。

ASP.NET的标准操作模型是,如果检测到401 Http Status代码,那么当您遇到时,它会自动重定向到登录页面,即使您通过Ajax调用进入也会发生这种情况。不幸的是,我也没有找到任何改变这种行为的方法。

我所做的是返回一个替代的,否则未使用的Http状态代码,我可以在客户端检测并以适当的方式处理。

因此,在我的身份验证过滤器中,如果是Ajax请求,则返回449,否则返回标准401.然后在客户端上,我可以检查XMLHttpRequest.status并在检测到449时采取适当的操作。

答案 2 :(得分:2)

您可以创建一个简单的授权属性过滤器(扩展AuthorizeAttribute类)并将其用于访问控制。然后尝试这样的事情:

protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
    if (filterContext.HttpContext.Request.IsAjaxRequest() ||  string.Compare("GET", filterContext.HttpContext.Request.HttpMethod, true) != 0)
    {
        // Returns 403.
        filterContext.Result = new HttpStatusCodeResult((int)HttpStatusCode.Forbidden);
    }
    else
    {
        // Returns 401.
        filterContext.Result = new HttpUnauthorizedResult();
    }
}

结果是,POST和AJAX请求将始终收到403响应,这使您更容易在javascript中处理您的ajax提交。至于非ajax帖子,响应是什么并不重要,因为你的用户不应该首先抓住提交表单:)

对于其他请求,该方法返回401表示FormsAuthentiction模块将接收,然后将您的响应重定向到登录页面。

答案 3 :(得分:1)

这是我设法阻止重定向到登录页面的方式。

在我的情况下,我想收到状态代码,以便在javascript中处理它:

protected void Application_EndRequest()
{
    if (Context.Response.StatusCode == 302 && Context.Request.Headers["X-Requested-With"] == "XMLHttpRequest")
    {
        Context.Response.Clear();
        Context.Response.StatusCode = 401;
    }
}

答案 4 :(得分:0)

我正在开发一个Web应用程序,它也暴露了一个web api,我没有看到这种行为。

当您使用REST时,您需要一种机制来对发出非公开端点/资源请求的用户进行身份验证。

这种机制可以是:

  • 随每个请求发送您的凭据。通常使用Http Basic Authentication。
  • 公开一个可以使用正确凭据命中一次的身份验证端点,如果身份验证成功,用户将获得一个令牌/票证。

如果你想要第二种选择,那么从简单到复杂的替代品会使你的解决方案或多或少变得强大。 Amazon's way众所周知且记录正确。但是,如果您的数据不是 敏感,有时只使用https将标记作为标题发送回来就足够了。

无论您使用的是基本HTTP身份验证还是世界上最安全的身份验证机制,您都需要某些来验证您在每个请求中发送的内容,并在上下文中填充Principal。请求。

这个某些东西可以在Asp.net Web Api中使用Message Handler aka DelegatingHandler来实现,它将处理并处理您的api控制器的每个请求并填充您的Principal,基于它找到的身份验证信息。

您可以找到DelegatingHandler实现here

的示例

在您拥有此基础架构之后,您应该能够在api控制器级别或操作级别使用 Syste.Web.HttpizeAttributeizeAttribute 又名[授权],根据您的需要。

如果DelegatingHandler无法根据手头的身份验证信息填充主体,那么您应该获得 401 Unauthorized w / o重定向。

不要忘记在App_Start上注册DelegatingHandler。

答案 5 :(得分:0)

您可以在配置身份时使用OnRedirectToLogin方法。