当授权失败,它返回一个局部视图控制器操作插入登录页面 [英] A controller action which returns a partial view inserts the logon page when authorization fails

查看:190
本文介绍了当授权失败,它返回一个局部视图控制器操作插入登录页面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个从加载使用jQuery的控制器操作的局部视图的视图。控制器动作装饰的授权属性,如果用户已经超时时,该操作被称为这一翻译被重定向到正确的登录页面,登录页面被插入在局部视图会去的看法。

有是另一篇文章<一个href=\"http://stackoverflow.com/questions/743252/how-may-i-best-use-the-authorize-attribute-with-ajax-and-partial-views\">here描述使用jQuery但遗憾的是它不包含任何code样品而这正是我需要的,因为我不是很熟悉的jQuery(以及新的web开发),我需要得到这个问题的尽快解决的解决方案我可以。

所有我想要做的就是将用户重定向到这听起来pretty直截了当给我,但到目前为止,它似乎并没有被正确的登录页面。如果jQuery是要走的路,可能有人请张贴code样本,这将真正帮助我。

感谢。


解决方案

解决方案1,得到的回答表明误差

结果
临ASP.NET MVC 2框架提供了一个解决方案为这个


  

如果一个Ajax请求
  拒绝授权,则通常
  你不想返回一个HTTP
  重定向到登录页面,因为
  您的客户端code不是
  期待这一点,可能会做一些事情
  不希望的诸如注入整个
  登录页面到中间
  任何网页的用户是在。代替,
  你要发回一个更有用
  信号传送到客户端code,
  也许在JSON格式,解释
  该请求没有被批准。
  你可以实现这个如下:


 公共类EnhancedAuthorizeAttribute:AuthorizeAttribute
{
    保护覆盖无效HandleUnauthorizedRequest(AuthorizationContext上下文)
    {
        如果(context.HttpContext.Request.IsAjaxRequest()){
            UrlHelper urlHelper =新UrlHelper(context.RequestContext);
            context.Result =新JsonResult {
                数据= {新
                    错误=NotAuthorized
                    LogOnUrl = urlHelper.Action(登录,帐户)
                },
                JsonRequestBehavior = JsonRequestBehavior.AllowGet
            };
        }
        其他
            base.HandleUnauthorizedRequest(上下文);
    }
}

您会再从控制器得到一个JSON对象 {'错误':'NotAuthorized','LogonUrl':'...'} 您可以然后用它来重定向用户。

和替代性的反应,如果你希望HTML,可能会返回一个简单的字符串,如 NotAuthorized:其中,YOUR_URL&GT; ,并检查响应此模式相匹配

结果

解决方案2,返回和处理 401 Unautorized 状态code

结果
因为这对每一个Ajax请求的成功回调进行检查,这得到相当繁琐。这将是很好,能够在全球范围内抓住这个情况。最好的解决办法是从服务器返回一个 401未授权状态code和使用jQuery的的 .ajaxError 抓住它,但是这是在IIS / ASP.NET有问题的,因为它是致命的承诺重定向你如果登录页面响应具有此状态code。只要&LT;认证&GT; 标签是的web.config 此重定向将发生的[1]如果你不做些什么事情。

所以,让我们做一些事情。 <一href=\"http://stackoverflow.com/questions/123726/401-response-$c$c-for-json-requests-with-asp-net-mvc/1072996#1072996\">This哈克的方式似乎不错。在你的Global.asax.cs

 保护无效Application_EndRequest()
{
    如果(Context.Response.Status code == 302安培;&安培; Context.Request.RequestContext.HttpContext.Request.IsAjaxRequest())
    {
        Context.Response.Clear();
        Context.Response.Status code = 401;
    }
}

(我很乐意,如果任何人任何更好的方法知道返回 401 状态code听到它。)

通过这样做,你是preventing重定向到登录页面时请求是一个Ajax请求的默认行为。因此,您可以使用默认的 AuthorizeAttribute ,因为它是,因为 Application_EndRequest 负责剩下的照顾。

现在,在jQuery的code,我们将使用 .ajaxError 函数来捕获错误。这是一个全球性的AJAX事件处理程序,这意味着它会拦截任何Ajax调用了一切错误。它可以连接到任何元素 - 在我的例子,我只是选择了原因它总是present

  $(身体)。ajaxError(函数(事件,XMLHtt prequest,ajaxOptions,thrownError){
    如果(XMLHtt prequest.status == 401){
        警报(未经授权);
    }
});

这样,你得到你重定向逻辑集中的有一个的地方,而无需检查每一个该死的Ajax请求的成功回调

结果

解决方案3,返回自定义标题

结果
<一href=\"http://stackoverflow.com/questions/199099/how-to-manage-a-redirect-request-after-a-jquery-ajax-call/579895#579895\">This答案提供了一种替代的解决方案。它采用了同一种全球性的事件处理程序,但跳过哈克位。它增加了一个自定义标题的页面,如果你不验证,该请求是一个Ajax请求,检查每个 <$这个头C $ C> .ajaxComplete 。请注意,在链接的答案提供的方法是不安全的,因为它会返回原来的视图与可能敏感的内容,并依赖于JavaScript,将用户重定向远离它。用位修改的这是相当真棒,因为它不需要任何黑客和逻辑可以集中于一个回调函数。我可以看到的唯一缺点是,它好好尝试与语义正确状态code答复,因为它实际上不是 200 OK ,因为你是 401未授权

结果
我们可以烤到另一个自定义此 EnhancedAuthorizationAttribute

 公共类EnhancedAuthorizeAttribute:AuthorizeAttribute
{
        保护覆盖无效HandleUnauthorizedRequest(AuthorizationContext上下文)
        {
            如果(context.HttpContext.Request.IsAjaxRequest())
            {
                context.HttpContext.Response.AddHeader(REQUIRES_AUTH,1);
                context.Result =新EmptyResult();
            }
            其他
            {
                base.HandleUnauthorizedRequest(上下文);
            }
        }
    }
}

现在,每一个Ajax请求完成时,检查此头:

  $('身体')。ajaxComplete(函数(事件,要求,设置){
    如果(request.getResponseHeader('REQUIRES_AUTH')==='1'){
        警报(未经授权);
    };
});

I have a view that loads a partial view from a controller action using jQuery. The controller action is decorated with the Authorize attribute and if the user has timed out when that action is called intead of being redirected to the proper LogOn page, the LogOn page gets inserted in the view where the partial view would have gone.

There is another post here that describes a solution using jQuery but unfortunately it doesn't include any code samples which is what I need because I'm not very familiar with jQuery (and new to web development) and I need to get this issue resolved as soon as I can.

All I want to do is redirect the user to the proper LogOn page which sounds pretty straight forward to me but so far it doesn't seem to be. If jQuery is the way to go, could someone please post a code sample, that would really help me out.

Thanks.

解决方案

Solution 1, return response indicating error


Pro ASP.NET MVC 2 Framework offers one solution for this

If an Ajax request is denied authorization, then usually you don’t want to return an HTTP redirection to the login page, because your client-side code is not expecting that and may do something unwanted such as injecting the entire login page into the middle of whatever page the user is on. Instead, you’ll want to send back a more useful signal to the client-side code, perhaps in JSON format, to explain that the request was not authorized. You could implement this as follows:

public class EnhancedAuthorizeAttribute : AuthorizeAttribute 
{ 
    protected override void HandleUnauthorizedRequest(AuthorizationContext context) 
    { 
        if (context.HttpContext.Request.IsAjaxRequest()) { 
            UrlHelper urlHelper = new UrlHelper(context.RequestContext); 
            context.Result = new JsonResult { 
                Data = new { 
                    Error = "NotAuthorized", 
                    LogOnUrl = urlHelper.Action("LogOn", "Account") 
                }, 
                JsonRequestBehavior = JsonRequestBehavior.AllowGet 
            }; 
        } 
        else 
            base.HandleUnauthorizedRequest(context); 
    } 
} 

You'd then get back a JSON object from the controller {'Error': 'NotAuthorized', 'LogonUrl': '...'} which you could then use to redirect the user.

And alternative response, if you're expecting HTML, could be to return a plain string, like NotAuthorized:<your_url> and check if the response matches this pattern.


Solution 2, return and handle 401 Unautorized status code


As this has to be checked on every ajax request's success callback, this gets quite tedious. It would be nice to be able to catch this case globally. The best solution would be to return a 401 Unauthorized status code from the server and use jQuery's .ajaxError to catch it, but this is problematic on IIS/ASP.NET, since it's deadly committed to redirecting you to the login page if the response has this statuscode. As long as the <authentication> tag is present in web.config this redirection will happen [1] if you don't do something about it.

So let's do something about it. This hacky way seemed nice. In your global.asax.cs

protected void Application_EndRequest()
{
    if (Context.Response.StatusCode == 302 && Context.Request.RequestContext.HttpContext.Request.IsAjaxRequest())
    {
        Context.Response.Clear();
        Context.Response.StatusCode = 401;
    }
}

(I'd love to hear it if anyone knows of any better methods to return a 401 status code.)

By doing this, you're preventing the default behaviour of redirecting to the logon page when the request is an ajax request. You can therefore use the default AuthorizeAttribute as it is, since Application_EndRequest takes care of the rest.

Now, in the jQuery code we'll use the .ajaxError function to catch the error. This is a global ajax event handler, meaning it will intercept every error made by any ajax call. It can be attached to any element - in my example I've just chosen body cause its always present

$("body").ajaxError(function(event, XMLHttpRequest, ajaxOptions, thrownError) {
    if (XMLHttpRequest.status == 401) {
        alert("unauthorized");
    }
});

This way you get your redirection logic centralized in one place, instead of having to check it on every damn ajax request success callback


Solution 3, return custom header


This answer offers an alternative solution. It uses the same kind of global event handler, but skips the hacky bits. It adds a custom header to the page if you're not authenticated and the request is an ajax request, and checks for this header on each .ajaxComplete. Note that the method provided in the linked answer is unsecure, as it will return the original view with possibly sensitive content and rely on javascript to redirect the user away from it. With a bit of modification it's quite awesome as it doesn't require any hacks and the logic can be centralized to one callback function. The only downside as I can see is that it doens't reply with the semantically correct status code, as it's actually not 200 OK because you're 401 Unauthorized


We can bake this into another custom EnhancedAuthorizationAttribute

public class EnhancedAuthorizeAttribute : AuthorizeAttribute
{
        protected override void HandleUnauthorizedRequest(AuthorizationContext context)
        {
            if (context.HttpContext.Request.IsAjaxRequest()) 
            {
                context.HttpContext.Response.AddHeader("REQUIRES_AUTH", "1");
                context.Result = new EmptyResult();
            }
            else
            {
                base.HandleUnauthorizedRequest(context);
            }
        }
    }
}

Now, every time an ajax request completes, you check for this header:

$('body').ajaxComplete(function(event,request,settings){
    if (request.getResponseHeader('REQUIRES_AUTH') === '1'){
        alert("unauthorized");
    };
});

这篇关于当授权失败,它返回一个局部视图控制器操作插入登录页面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆