ASP.NET Core HttpContext.Session.Clear() 在部署到 IIS 时未正确清除会话

问题描述 投票:0回答:1

语言: ASP.NET Core MVC 中的 C# 和 HTML Razor

上下文/问题; 在 Visual Studio 中调试时,我使用 HttpContext.Session 存储特定于用户的信息,按预期在注销操作函数中调用 HttpContext.Session.Clear() 并清除所有会话变量。但是,当将同一应用程序发布和部署到 IIS 时,单击注销,会话变量被清除,但大约 10 - 12 秒后,会话变量重新出现,就像它们从未被清除一样......有时也有这样的情况:会话确实保持清除状态,但大多数情况下都会出现此问题。

这会导致注销按钮将用户注销大约 10 秒,然后用户信息重新出现,从而使网站看到用户再次登录。

从我的代码中截取:

家庭控制器:

        [Route("logout")]
        [HttpGet]
        public IActionResult Logout()
        {
            HttpContext.Session.Clear();
            return RedirectToAction("Index");
        }

cshtml/Razor 视图/页面:

        <a class="nav-link text-dark" asp-controller="Home" asp-action="Logout"><b>Logout</b></a>

仅供参考:我正在使用我在网上找到的 SessionExtension,它允许我直接在 Session 中存储对象,而无需手动对它们进行编码/解码。我将用户信息存储为字典,这样我就可以通过页面中的 HttpContextAccessor 轻松访问它,以便在需要时获取权限。我选择了这个,而不是每次需要页面权限时都访问数据库。相反,在登录时访问数据库一次并将收集到的信息存储在会话中。我不确定这是否是造成这种情况的原因,但我想我应该包含这一点以获得更多背景信息。

SessionExtensions.cs:

using Newtonsoft.Json;
#nullable enable
namespace Microsoft.AspNetCore.Http
{
    public static class SessionExtensions
    {
        public static void SetObject(this ISession session, string key, object value)
        {
            session.SetString(key, JsonConvert.SerializeObject(value));
        }

        public static T GetObject<T>(this ISession session, string key)
        {
            var value = session.GetString(key);
            return value == null ? default(T) : JsonConvert.DeserializeObject<T>(value);
        }
    }
}

这是我在会话中遇到的唯一问题,用户之间的其他一切同时工作正常,只是注销就是问题。当注销按钮起作用时,其他一切也都可以正常工作。

我尝试过的事情:

使用 VS 调试 IIS 上部署的实例,单击注销按钮后,会话保持清除状态(返回 Null)约 10 - 12 秒,然后所有内容重新出现,就像从未清除过一样。

在我的开发人员上调试项目。单击注销后,VS 内的计算机并没有看到相同的行为,会话将无限期地保持清除状态。 (返回空)

清除客户端浏览器的cookie。

重新启动运行 IIS 和站点的服务器。

从 IIS 中删除站点并重新传输已发布的文件,然后再次添加。对发布设置为“调试”和“发布”的配置执行相同的操作。功能没有变化。

更新所有 NuGet 包,最近还更新到 .NET 7.0 框架。

我可能会遗漏一些东西,因为我对 C#、ASP.NET Core MVC 和 Razor 页面,甚至 Stack Overflow 还很陌生。如果需要添加更多信息来帮助回答问题,请发表评论。

编辑: Program.cs 中设置的会话超时(空闲超时)always正确地清除了会话。

编辑: 我可以通过在单击注销时将每个会话变量设置为 null 来解决此问题。但这似乎是一种绕行的方法,如果我将来添加另一个变量,可能很容易出错。这应该是解决方案吗?

编辑: 我之前提到的将每个变量设置为 null 的修复方法并不能解决所有问题。我实际上注意到会话中出现的其他问题。我无法确定,因为它是随机的,有时设置会话变量不需要,有时需要,有时有时需要......

看起来会话只是忽略了对其方法的一些调用,或者当它跟随它们时,它只生效 10 秒......

编辑: 我已经尝试了一切可以解决这个问题的方法,直到我偶然发现了这个问题。

@{var IPAddress = HttpContextAccessor.HttpContext.Request.HttpContext.Connection.RemoteIpAddress.ToString();


Ping pingSender = new Ping();
PingReply reply1 = pingSender.Send(IPAddress);
PingReply reply2 = pingSender.Send(IPAddress);
PingReply reply3 = pingSender.Send(IPAddress);

long[] ReplyTimes = { reply1.RoundtripTime, reply2.RoundtripTime, reply3.RoundtripTime};}
@ReplyTimes

这是我在调试页面中设置的一小段代码,它可以为我提供平均 3 个样本的当前 ping 值。由于某种原因,删除此代码解决了我迄今为止可以告诉的所有问题。经过进一步研究,似乎每次发生会话更新(更改变量)时,它都会保存更改,然后在 10 秒后恢复。

奇怪的部分是,再过 10 秒后,它有时会再次恢复到最新的变量,然后重复......基本上导致变量自行更改。此调试页面仅在登录时显示,所以我仍然有点困惑此页面上的代码如何影响注销的能力(即使未加载调试页面,会话清除也会在 10 秒后重新出现)

我仔细检查了一下,始终只有 1 个会话 cookie。

我不知道为什么删除此代码可以解决问题。也许以某种方式访问请求远程 IP 地址会导致不可预见的问题?

我将其添加为编辑而不是答案,因为这并不能真正回答为什么这会导致会话按原样运行。

c# asp.net-core iis razor asp.net-core-mvc
1个回答
0
投票

我也有类似的问题。我这样做是为了解决这个问题。

更改:

<a class="nav-link text-dark" asp-controller="Home" asp-action="Logout"><b>Logout</b></a>

致:

<a class="nav-link text-dark" href="/logout"><b>Logout</b></a>

还创建了一个新控制器:

public class LogoutController(ILogger<LogoutController> logger) : Controller
{
   private readonly ILogger<LogoutController> _logger = logger;

   public IActionResult Index()
   {

      // Clear the session data 
      HttpContext.Session.Clear();
      Response.Cookies.Delete(".AspNetCore.Session");

      return RedirectPermanent("login");
   }
}

以及program.cs中的新路由映射

app.MapControllerRoute(name: "logout",
pattern: "{controller=Logout}/{action=Index}/{id?}");
© www.soinside.com 2019 - 2024. All rights reserved.