2016-08-19 29 views
8

在我们的MVC网站上,我们使用Authorize属性保护我们的端点,但是我希望在出现这种情况时将用户重定向到登录屏幕。我的第一个解决方案是对重定向Application_EndRequestGlobal.asax.cs如何在未授权的情况下重定向到我的登录屏幕,同时在MVC中返回401状态码?

protected void Application_EndRequest(object sender, EventArgs e) 
    { 
     if (Response.StatusCode == (int) HttpStatusCode.Unauthorized) 
     { 
      Response.ClearContent(); 
      Response.Redirect("/Account/Login"); 
     } 
    } 

这样做的问题是,我们的一些观点是由AJAX加载,在这种情况下,我们不希望显示动态加载专区内的登录画面(这发生在例如退出后按下后退按钮时)。如果请求仍然返回登录屏幕,但使用401未授权状态代码,以便我们可以检测到此事件,会更好。显然这不适用于这种方法,因为重定向依赖于302状态码。

相反,我宁愿用401状态代码在Application_EndRequest内插入登录屏幕内容。因此,代替Response.Redirect的,我尝试这样做:

  ... 
      Response.ClearContent(); 
      Server.TransferRequest("~/Account/Login"); 
      Response.StatusCode = (int) HttpStatusCode.Unauthorized; 
      ... 

重定向工作得很好,但由于这种执行了新的要求,我不能设置状态代码以这种方式,我也得到了200元。不过对于检测未经授权的请求没有好处。

我也试过:

  ... 
      Response.ClearContent(); 
      Server.Transfer("~/Account/Login"); 
      Response.StatusCode = (int) HttpStatusCode.Unauthorized; 
      ... 

但我得到一个异常“为/帐号/登录错误执行子请求。”

我也试过:

  ... 
      Response.ClearContent(); 
      HttpContext.Current.RewritePath("~/Account/Login"); 
      Response.StatusCode = (int) HttpStatusCode.Unauthorized; 
      Response.End(); 
      ... 

但这抛出一个异常 “线程已被中止”。我不确定如果Response.End()是必需的但没有它,我只是得到一个标准的IIS 401错误。

如何返回我的登录屏幕的内容,但带有401状态码?

+0

尝试使用401自定义错误处理来返回登录视图。 –

回答

4

我尝试了很多不同的方法,所有这些方法都有自己的鬼祟问题。不知道如何您的解决方案是安装程序,但如果你需要执行传输,你可以使用以下命令:

定制AuthorizeAttribute

public class CustomAuthorizeAttribute : AuthorizeAttribute 
{ 
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) 
    { 
     filterContext.RequestContext.HttpContext.Server.TransferRequest("/Account/Login/?NOT_AUTHORISED=TRUE", false); 
    } 
} 

你需要传递一个消息到下一个请求,使用查询字符串似乎做的伎俩。尽管您需要记住任何人都可以设置QS参数。

设置状态码

protected void Application_EndRequest(object sender, EventArgs e) 
{ 
    if (Request["NOT_AUTHORISED"] == "TRUE") 
    { 
     Response.StatusCode = (int) HttpStatusCode.Unauthorized; 
    } 
} 

演示

有没有重定向和HTTP状态代码设置为401

enter image description here

8

发送401和的ViewObject或RedirectObject是不是如何设计的MVC框架工作: - 几个职位巧妙地表明,返回使用View和授权过滤器来创建401。

我指定的MVC框架,而这甚至不是使用HTTP协议的首选方式。

  • 当您在MVC应用重定向,你已经创建了一个RedirectResult
  • 当您MVC应用程序返回与该控制器的View()方法的调用,一个ViewResult创建

是否a 重定向或一个查看最终到达客户端浏览器或者,

  • HTTP Return Code的 - 成功将返回

或者

  • HTTP Return Code的 - 重定向将返回

这种约定的原因是,服务器是“处理”的重定向。如果用户未被授权,服务器会将用户重定向到登录页面。

侨胞,在AJAX或异步HTTP请求,只要返回一个HTML 查看,HTTP请求被认为是成功的。对于异步请求,不会返回重定向(302)。


发送错误代码到客户端:

如果你想返回401未经授权到客户端,这通常意味着要在客户端“处理”未经授权的请求导航到登录或错误视图。

$.ajax({ 
    url: loginURL, 
    data: $("#form").serialize(), 
    type: "POST", 
    dataType: "html" 
}) 
.success(function (result, status) { 
      /*additional logic*/ 
}) 
.error(function (xhr, status) { 
    if (xhr.status == 401) 
    { 
     window.location = unauthorizedUrl; //redirect to unauthorized url 
    } 
}); 

如果你想重定向到登录页面,并显示错误

你的问题更有意义,如果你想重定向到登录页面,并显示错误

Bad Login Attempt

然后,约定是将您的错误消息添加到Viewbag或的ModelState错误

如:

 var user = await signInManager.UserManager.FindByNameAsync(model.UserName); 

       ModelState.AddModelError("", "Invalid username or password."); 
       return View(model); 

在你看来,有代码,查找错误:

一个ValidationSummary将皮卡模型误差

  @Html.ValidationSummary(true) 

错误登录尝试的具体示例并不完全对您的示例说话。

我无法找到重定向用户的图像,因为他们没有被授权,但在这种情况下,逻辑类似。错误消息可以用查询字符串Viewbag等填充

+0

在我在下面提供的答案中,我返回了一个ViewObject和一个401状态码。 – timkly

+0

@timkly,你是对的。我应该编辑我的帖子,并承认这显然是可能的。 –

6

你会非常想使用自定义AuthorizeAtrribute,然后挂接到HandleUnauthorizedRequest方法,并从通过设置返回一个以你的登录页面控制器和视图在AuthorizationContext中调用。

public class MyAuthorizeAttribute : AuthorizeAttribute 
{ 
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) 
    { 
     if (!filterContext.HttpContext.User.Identity.IsAuthenticated) 
     { 
      filterContext.RouteData.Values["controller"] = "home"; 
      filterContext.RouteData.Values["action"] = "login"; 

      filterContext.Result = new ViewResult(); 
      filterContext.HttpContext.Response.Clear(); 
      filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized; 
      filterContext.HttpContext.Response.TrySkipIisCustomErrors = true; 
      filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true; 
     } 
    } 
} 

注意:为这个诀窍是确保你设置以下值为true,以避免窗体身份验证接管响应,一旦你设置了401个状态。

HttpContext.Response.SuppressFormsAuthenticationRedirect = true; 
相关问题