Azure AD B2C、ASP.NET Mvc和JQuery AJAX -通过Ajax问题刷新过期令牌

dpiehjr4  于 2022-12-03  发布在  jQuery
关注(0)|答案(1)|浏览(125)

我有一个使用.NET 7.0和Mvc/Razor构建的Web应用程序。此应用程序由Microsoft身份库和Azure AD B2C保护。我已将[Authorize]属性添加到Mvc控制器,并且运行良好。我可以登录,页面可以正确访问控制器,并且如果身份验证令牌过期,它们将正确刷新,等等。
当我试图通过页面中的JQuery AJAX 调用访问mvc控制器中的一些端点时,问题就出现了。当我进行调用时,auth令牌已经过期,我看到302响应(我相信这是正确的行为),但随后我得到了CORS error。但更具体地说,Chrome DevTools控制台中出现的错误是:

Access to XMLHttpRequest at 'https://xxxxx.b2clogin.com/xxxxx.onmicrosoft.com/b2c_1a_signup_signin/oauth2/v2.0/authorize?<additional stuff>' (redirected from 'http://localhost:57152/<mvc controller endpoint>?callback=jQuery360002914740315700981_1669878277934&_=1669878277935') from origin 'http://localhost:57152' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

我认为处理的方法是拦截302响应,将其更改为401(未授权)响应,然后让 AJAX 通过给用户一个登录页面来处理401。这是正确的方法吗?如果是,我如何去拦截302响应呢?因为我试图用控制器上的一个自定义Authorize属性来完成这一任务,但在属性有机会拦截之前,CORS错误发生了。
我已经花了很多时间寻找解决这个问题的方法,所以希望有人经历过这个相同的问题,并设法解决它。

cld4siwp

cld4siwp1#

最后,我通过做两件事解决了这个问题......向startup.cs添加一些中间件,并处理JQuery方法.ajaxError
中间件,它拦截一个请求,判断它是否有一个302响应(典型的是当一个授权令牌被刷新时),并且请求是一个 AJAX 请求。如果是,将响应更改为401 unauthorized。

app.Use(async (context, next) =>
{
    await next.Invoke();

    // Is the response a redirect?
    if (context.Response.StatusCode == StatusCodes.Status302Found)
    {
        // Is the request an AJAX request?
        if (context.Request.Headers.TryGetValue("X-Requested-With", out var headerValue) && headerValue == "XMLHttpRequest")
        {
            context.Response.StatusCode = StatusCodes.Status401Unauthorized;
        }
    }
});

JQuery AJAX 错误方法检查错误是否是401错误。如果是,则将浏览器发送到登录页面,该页面将自动刷新auth令牌,或者提示用户再次登录。在下面的示例中,我使用DevExpress控件让用户知道会话已过期。

$(document).ajaxError(function(event, request, settings) {
    if (request.status === 401) {
        var result = DevExpress.ui.dialog.alert("<p>Your session has expired and we will attempt to log you in again.</p><p>Please note, this will refresh the page and you will lose unsaved data.</p>", "Session Expired");
        result.done(function () {
            var signInUri = '@(Url.Content("~/MicrosoftIdentity/Account/SignIn?redirectUri="))' + encodeURIComponent(location.pathname);
            location.href = signInUri;
        });
    }
});

这对我来说很有效,但我对以更健壮、更优雅的方式处理这种情况的解决方案持开放态度。

相关问题