对于我的网站,我希望获得安全控制器(或操作)的以下行为
如果用户将正常请求重定向到登录页面(我很容易就能做到)
如果请求是Ajax类型Request.IsAjaxRequest()==true
,则返回状态码401
如何为此创建过滤器?
答案 0 :(得分:27)
public class MyCustomAuthorize : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
//if ajax request set status code and end Response
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
filterContext.HttpContext.Response.StatusCode = 401;
filterContext.HttpContext.Response.End();
}
base.HandleUnauthorizedRequest(filterContext);
}
}
如上所述创建一个过滤器,如果通过ajax发出请求,它将返回状态码401以表示未经授权的请求。
如果您使用的是jQuery,可以按照以下方式进行操作
jQuery.ajax({
statusCode: {
401: function() {
alert('unauthrized');
},
/*other options*/
});
答案 1 :(得分:3)
除了接受的答案之外,我还需要放入这行代码以防止FormsAuthentication重定向到登录页面。
filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;
然后我删除了 filterContext.HttpContext.Response.End();var unauthorizedResult = new JsonResult
{
Data = new ErrorResult() {Success = 0, Error = "Forbidden"},
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
// status code
filterContext.HttpContext.Response.StatusCode = (int) HttpStatusCode.Unauthorized;
// return data
filterContext.Result = unauthorizedResult;
filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;
}
答案 2 :(得分:1)
您的问题不在于AJAX请求,您的问题是返回HTTP 401 Unauthorized响应,因为您使用表单身份验证。此响应代码告诉框架它应该使用HTTP 302响应将用户代理重定向到您的登录页面。这就是设置“正常”请求重定向很容易的原因 - 它是自动完成的
为了回答你的问题,我有类似的问题,我最终得到的解决方案是不使用表单身份验证。我实现了一个自定义授权属性,可以手动处理这两种情况。我不确定这是否是最好的方法,但确实有效。我对其他人对此解决方案的看法或其他解决方案感兴趣
幸运的是,您仍然可以使用FormsAuthentication
类为您处理cookie,但您必须从Web.config文件中删除表单身份验证配置。当用户登录时,使用FormsAuthentication.SetAuthCookie
来设置cookie(您可能已经这样做了)。其次,在您的授权属性中,您从请求中获取cookie并使用FormsAuthentication.Decrypt
对其进行解密。如果它存在且有效,则根据此cookie将用户设置在HttpContext
中,因为表单身份验证将不再为您执行此操作。如果不是,您可以重定向到登录页面或返回401,具体取决于它是否是AJAX调用。
答案 3 :(得分:1)
您可以使用ajaxonly来限制对ajax actionresult的访问
答案 4 :(得分:1)
您只需返回 HttpUnauthorizedResult 。
注意:这可能会导致MVC框架返回登录页面。
public ActionResult FailResult()
{
return new HttpUnauthorizedResult();
}
答案 5 :(得分:0)
一种简单的方法是检查SignIn操作
public ActionResult SignIn()
{
if (Request.IsAjaxRequest())
{
// you could return a partial view that has this script instead
return Content("<script>window.location = '" + Url.Action("SignIn", "Account") + "'</script>");
}
...
return View();