在ajax表单发布之前检查mvc中的http授权

Checking for http authorization in mvc before ajax form post

提问人:Matt Smith 提问时间:5/15/2009 最后编辑:Matt Smith 更新时间:1/17/2012 访问量:5025

问:

在构建将 jquery ajax 整合到其 GUI 中的内容管理系统时,我遇到了一个障碍。似乎有些客户花了太长时间思考他们要写什么,因此服务器会话将他们注销,自然是他们对此一无所知的网络。当他们尝试提交更改时,我使用对服务器的 ajax 调用来保存数据。

我预计接下来会发生什么,MVC 服务器应用程序将返回“401 未经授权”状态。然后,我可以让我的jquery ajax对象要求用户登录,然后在用户获得授权后重新发送更改。

但是,实际从 MVC 应用程序返回的是“302 Found”状态和指向我的登录表单页面的重定向 URL。登录窗体页返回“200 OK”状态代码,jquery ajax 对象调用成功事件,告诉用户一切都成功了,因为这就是 MVC 应用程序所说的。

有没有办法让 MVC 应用程序按照我认为应该的方式播放,或者我是否必须修改我的 jquery ajax 事件来检测登录页面?

更新:

我使用 reflector 查看了 MVC 代码和 authorize 属性,返回一个 NotAuthorizedResult,其代码如下 (0x191 = 401)

public override void ExecuteResult(ControllerContext context)  
{  
    if (context == null)  
    {  
        throw new ArgumentNullException("context");  
    }  
    context.HttpContext.Response.StatusCode = 0x191;  
}

我在想,也许Forms Authorization HttpModule看到了401并强制重定向。

jQuery ASP.NET-MVC AJAX 身份验证

评论


答:

6赞 Simon Farrow 5/15/2009 #1

你可以尝试这样的事情:

    void context_EndRequest(object sender, EventArgs e)
    {
        var app = sender as HttpApplication;
        var response = app.Response;
        var request = app.Request;

        if ((response.StatusCode == 302) && IsAjaxRequest(request))
            response.StatusCode = 401;
    }

在 HttpModule 中,它将依次在 FormsAuth 模块之后,因此将更正状态代码。不漂亮但有效。

评论

0赞 womp 4/24/2010
在 .Net 4.0 中(也许还有其他版本,我不知道),FormsAuthentication 在 EndRequest 处理程序中执行重定向。我发现如果我使用 EndRequest,FormsAuth 没有处理响应,但使用 PreSendRequestHeaders 事件的效果要好得多(在 EndRequest 之后)。谢谢你的这篇精彩文章。
5赞 user342706 7/15/2011 #2

我真的很喜欢这个解决方案。通过将 ajax 请求的 302 响应更改为 401,它允许您在客户端设置 ajax 以监视任何查找 401 的 ajax 请求,如果找到 401 重定向到登录页面。非常简单有效。

Global.asax:

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

客户端代码:

 $(function () {
      $.ajaxSetup({
        statusCode: {
          401: function () {
            location.href = '/Logon.aspx?ReturnUrl=' + location.pathname;
          }
        }
      });
    });
1赞 Uffe Friis Lichtenberg 1/17/2012 #3

我发现一种更轻量级的方法就是简单地将自定义 HTTP 标头添加到登录页面,然后在 AJAX 成功回调中检查它是否存在。

即。在 LoginController 中(这是一个 MVC 项目,但相同的原则应该适用于其他 ASP.NET 解决方案):

public ActionResult Login(string returnUrl = "")
{
    Response.AddHeader("X-Unauthorized", "true");
    ...

然后在客户端 AJAX 处理程序中:

success: function(data, textStatus, jqXhr)
{
    if (jqXhr.getResponseHeader("X-Unauthorized"))
    {
        ...

这至少对我有用。