表单身份验证是否在未经授权的访问时将登录页面作为html返回?

时间:2013-05-11 19:20:49

标签: asp.net-mvc asp.net-mvc-3 forms-authentication

在我的ASP.Net MVC应用程序中,如果用户在ajax调用期间注销或Session超时,则会将登录页面作为html返回到调用javascript ajax调用。这会导致客户端出错,因为它无法解析html。

我想覆盖handleunauthorizedrequest属性上的authorize,但即使在覆盖它之后,调试时也不会遇到此问题,但仍会返回登录页面。

如果请求是ajax请求且请求未经授权,我的目标是返回 401 状态代码。

这个问题的解决方案是什么,我仍然无法理解为什么handleunauthorizedrequest没有被击中,是不是被覆盖了?

4 个答案:

答案 0 :(得分:0)

以下情况应该有效。

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        var request = filterContext.HttpContext.Request;
        var response = filterContext.HttpContext.Response;
        if (request.IsAjaxRequest())
        {
            response.StatusCode = 401;
            filterContext.Result = new EmptyResult();
        }
        else
        {
            base.HandleUnauthorizedRequest(filterContext);
        }
    }
}

然后在控制器或操作中使用过滤器

//instead of Authorize
[CustomAuthorize]
public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
}

在客户端添加ajaxError事件的挂钩并检查状态代码401

$(function(){
    $(document).ajaxError(function (e, xhr, opts) {
        if (401 == xhr.status) {
            //do whatever you like
            //return document.location = document.location;
        }
    });
});

希望这会有所帮助。

答案 1 :(得分:0)

默认AuthorizeAttribute不处理AjaxRequest。您需要编写自己的实现。我在下面给出了一个示例实现,您可以根据需要进行自定义。

我在homecontroller中添加了一个动作来返回一个JsonResult并应用了默认的[Authorize]属性。

    [Authorize]
    public ActionResult SayHello()
    {
        object result=new {status="200",res="Hello"};
        return Json(result, JsonRequestBehavior.AllowGet);
    }

在视图中,我添加了一个简单的ajax事件来调用动作并将res显示为警告。

    <h3>
    <a id="anchorSayHello">Say Hello</a>
</h3>
@section Scripts{
    <script>
        $('#anchorSayHello').click(function () {
            $.ajax('/Home/SayHello', {
                success: function(data) {
                    var str = data.res;
                    alert(str);
                }
            });
            return false;
        });
    </script>

}

因为,你已经告诉它将以未授权方式返回html响应。

enter image description here

现在,让我们实现自定义Authorize attribtue并应用于操作

 public class TestAuthorize : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
        {
            object res = new { status = "404", redirect = "/Account/Login" };
            filterContext.Result = new JsonResult() { Data = res, JsonRequestBehavior = JsonRequestBehavior.AllowGet };

            return;
        }
        base.HandleUnauthorizedRequest(filterContext);
    }
}

现在让我们将Javascript修改为,

$('#anchorSayHello').click(function () {
            $.ajax('/Home/SayHello', {
                success: function (data) {
                    if (data.status === '200') {
                        var str = data.res;
                        alert(str);
                    } else {
                        window.location = data.redirect;
                    }
                }
            });
            return false;
        });

现在它应该按预期工作,对于ajax请求,它也会重定向到登录页面。

enter image description here

答案 2 :(得分:0)

jquery中的jqXhr对象ajax有一个state属性,可以这样访问:

 jqXhr.state()

如果state属性的值被“拒绝”,则表示没有返回json结果,并且您的调用被拒绝。

我使用此属性的值来确定会话是否已超时,并且我能够优雅地重定向到登录页面。

答案 3 :(得分:0)

从.NET 4.5开始,正确的答案是将HttpResponse[Base].SuppressFormsAuthenticationRedirect设置为true:

if (!httpContext.Request.IsAuthenticated)
{
    if (httpContext.Request.IsAjaxRequest())
    {
        httpContext.Response.SuppressFormsAuthenticationRedirect = true;
    }
    return new HttpUnauthorizedResult();
}