在对 IIS 服务器上托管的 .NET CORE 2.1 应用程序进行一次 AJAX 调用后,会话状态被清除或丢失

Session State being cleared or lost after one AJAX call to .NET CORE 2.1 application hosted on IIS server

我已经 运行 解决了这个问题,我为此绞尽脑汁好几个小时了。

问题:我在 Login 上创建的会话状态在调用同样位于 .NET CORE 2.1 中的 API 控制器后神秘地被清除或丢失。当我调用如下所示的 API 方法时会发生这种情况:

    [Authorize(Policy = "AdminViewPolicy")]
    [HttpGet("GetAllUsersId")]
    public IActionResult GetAllUsersId()
    {
        var user = _userService.GetAllUsersId();
        return Ok(new
        {
            data = user
        });
    }

此方法的角色和其他方面工作正常。这就是我如何调用此操作方法:

$.ajax({
    url: "https://www.someworkingwebsite.com/api/Users/GetAllUsersId",
    type: "GET",
    async: false,
    dataType: "json",
    contentType: "application/json",
    data: {},
    credentials: 'include',
    xhrFields: {
        withCredentials: true
    },
    beforeSend: function (xhr) {
        xhr.setRequestHeader("Authorization", window.localStorage.getItem("authToken"));
    },
    success: function (data) {
        console.log(data);
        var html = [];
        for (var i in data["data"]) {
            var id = data["data"][i]["fullName"] + "###" + data["data"][i]["uuid"] + "###" + data["data"][i]["id"];
            //var id = data["data"][i]["uuid"] + "###" + data["data"][i]["id"];
            html.push(id);
        }
        /*initiate the autocomplete function on the "searchInput" element, and pass along the countries array as possible autocomplete values:*/
        autocomplete(document.getElementById("searchInput"), html);
    },
    error: function () {
        console.log("Error" + data);
    },
});

我的 API 项目的 Startup.cs 配置如下所示:

public void ConfigureServices(IServiceCollection services)
{
services.AddCors();
           services.Configure<CookiePolicyOptions>(options =>
               {
                   // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                   options.CheckConsentNeeded = context => false;
                   options.MinimumSameSitePolicy = SameSiteMode.None;
               });

            services.AddSession(options =>
            {
                options.IdleTimeout = TimeSpan.FromMinutes(30);

            });

            services.AddMvc(options =>
            {
                options.Filters.Add(typeof(ValidateModelAttribute));

            })
            .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

        services.AddHttpContextAccessor();
}


    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
      //Other code omitted for brevity 
            app.UseForwardedHeaders();

            // global cors policy
            app.UseCors(x => x
                .AllowAnyOrigin()
                .AllowAnyMethod()
                .AllowAnyHeader()
                .AllowCredentials());

            app.UseAuthentication();
            app.UseSession();
    }

我用于检查 Session 的客户端过滤器看起来像:

public override void OnActionExecuting(ActionExecutingContext context)
{
    if (Context.Current.Session == null || !Context.Current.Session.TryGetValue("UserID", out byte[] val))
    {
        context.Result =
            new RedirectToRouteResult(new RouteValueDictionary(new
            {
                controller = "Pages",
                action = "SessionTimeout"
            }));
    }
    base.OnActionExecuting(context);
}

棘手的部分。当我从我的 View 调用 AJAX 函数时,AJAX 成功调用 API 方法并获取所需的数据,而且 AJAX调用以某种方式清除了我的会话,因为一旦我导航到其他页面或提交表单,就会调用上面显示的 SessionTimeout 属性并将我踢出系统。

我检查了我的网络浏览器上的所有控制台日志、网络请求、应用程序存储,但我找不到罪魁祸首。我还检查了 API 和客户端中的逻辑,看看我是否犯了这个重大错误,但我找不到任何暗示这一点的东西。

由于 API 和客户端托管在 IIS 服务器上,我认为该死的环境可能正在做一些事情,但没有,我也找不到任何人可以责怪那里。

所以折腾了一大堆,终于决定请教高手了。如果有人可以帮助我 hopefully 解决我的这个问题,那就太好了。

感谢期待。

抱歉,我没有注意到您使用的是 ASP.NET Core 2.1。 2.1 版及更高版本具有影响 .AspNetCore.Session cookie 的默认行为的 GDPR 相关更改,如:默认情况下不生成。

假设您的应用程序不 运行 违反 GDPR,您可以通过对 ConfigureServices() 方法进行两处更改来启用之前的 Cookie-Session 映射行为。

您已经拥有的第一个是将 CookiePolicyOptions.CheckConsentNeedtrue 更改为 false(您已经这样做):

    services.Configure<CookiePolicyOptions>(options =>
    {
        // This lambda determines whether user consent for non-essential cookies is needed for a given request.
        options.CheckConsentNeeded = context => false;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });

第二个是将会话 cookie 标记为必需:

    services.AddSession(opts => 
    {
        opts.Cookie.IsEssential = true; // make the session cookie Essential
    });

Why isn't my session state working in ASP.NET Core? Session state, GDPR, and non-essential cookies 中阅读更多相关信息。

好的,关于这个问题,我找到的解决方案是更改每个相互交互的应用程序的会话 cookie 名称。

In Startup / Configure(),更改应用程序的cookie名称:

app.UseSession(new SessionOptions() { Cookie = new CookieBuilder() { Name = ".AspNetCore.Session.MyApp1"}});

我不完全知道为什么会这样。如果有人能对这个问题有更多的了解,我将不胜感激。

谢谢,我希望这对面临类似问题的人有所帮助。