简体   繁体   English

在.NET Core MVC中使用Ajax处理会话超时

[英]Handling session timeout with Ajax in .NET Core MVC

I have a regular application using cookie based authentication. 我有一个使用基于cookie的身份验证的常规应用程序。 This is how it's configured: 它是这样配置的:

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication("Login")
            .AddCookie("Login", c => {
                c.ClaimsIssuer = "Myself";
                c.LoginPath = new PathString("/Home/Login");
                c.AccessDeniedPath = new PathString("/Home/Denied");
            }); 
}

This works for my regular actions: 这适用于我的常规操作:

[Authorize]
public IActionResult Users()
{
    return View();
}       

But doesn't work well for my ajax requests: 但是对于我的ajax请求来说效果不佳:

[Authorize, HttpPost("Api/UpdateUserInfo"), ValidateAntiForgeryToken, Produces("application/json")]
public IActionResult UpdateUserInfo([FromBody] Request<User> request)
{
    Response<User> response = request.DoWhatYouNeed();

    return Json(response);
}

The problem is that when the session expires, the MVC engine will redirect the action to the login page, and my ajax call will receive that. 问题是,当会话到期时,MVC引擎会将操作重定向到登录页面,而我的ajax调用将收到该消息。 I'd like it to return the status code of 401 so I can redirect the user back to the login page when it's an ajax request. 我希望它返回401的状态代码,这样当它是ajax请求时,我可以将用户重定向回登录页面。 I tried writing a policy, but I can't figure how to unset or make it ignore the default redirect to login page from the authentication service. 我尝试编写策略,但是无法弄清楚如何取消设置或使其忽略从身份验证服务到登录页面的默认重定向。

public class AuthorizeAjax : AuthorizationHandler<AuthorizeAjax>, IAuthorizationRequirement
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, AuthorizeAjax requirement)
    {
        if (context.User.Identity.IsAuthenticated)
        {
            context.Succeed(requirement);
        }
        else
        {   
            context.Fail();
            if (context.Resource is AuthorizationFilterContext redirectContext)
            {
                // - This is null already, and the redirect to login will still happen after this.
                redirectContext.Result = null;
            }
        }

        return Task.CompletedTask;
    }
}

How can I do this? 我怎样才能做到这一点?

Edit: After a lot of googling, I found this new way of handling it in version 2.0: 编辑:经过大量的搜索之后,我在2.0版中发现了这种处理它的新方法:

services.AddAuthentication("Login")
        .AddCookie("Login", c => {
                   c.ClaimsIssuer = "Myself";
                   c.LoginPath = new PathString("/Home/Login");
                   c.Events.OnRedirectToLogin = (context) =>
                   {
                       // - Or a better way to detect it's an ajax request
                       if (context.Request.Headers["Content-Type"] == "application/json")
                       {
                           context.HttpContext.Response.StatusCode = 401;
                       }
                       else
                       {
                           context.Response.Redirect(context.RedirectUri);
                       }

                       return Task.CompletedTask;
                   };                       
        });

And it works for now! 现在就可以使用!

What you need can be achieved by extending AuthorizeAttribute class. 您可以通过扩展AuthorizeAttribute类来实现。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class AjaxAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (filterContext.HttpContext.Request.IsAjaxRequest())
        {
             filterContext.HttpContext.Response.StatusCode = 401;
             filterContext.Result = new JsonResult
             {
                 Data = new { Success = false, Data = "Unauthorized" },
                 ContentEncoding = System.Text.Encoding.UTF8,
                 ContentType = "application/json",
                 JsonRequestBehavior = JsonRequestBehavior.AllowGet
             };
        else
        {
            base.HandleUnauthorizedRequest(filterContext);
        }
    }
}

You can then specify this attribute on Ajax methods. 然后,您可以在Ajax方法上指定此属性。

Hope this helps. 希望这可以帮助。

Reference: http://benedict-chan.github.io/blog/2014/02/11/asp-dot-net-mvc-how-to-handle-unauthorized-response-in-json-for-your-api/ 参考: http : //benedict-chan.github.io/blog/2014/02/11/asp-dot-net-mvc-how-to-handle-unauthorized-response-in-json-for-your-api/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM