最近公司采用asp.net core的站点在外测环境中,总是发现存在session丢失的情况。排查了好久,客户端.AspNetCore.Session的cookie未丢失,session的分布式缓存采用的redis主从复制也未发现问题,也想用cookie的变通解决方案,但是没解决根本问题,总是觉得如鱼梗在喉的不爽。后来在排查的过程中,发现同一个客户端通过nginx居然有时候会负载到不同的网站服务器上,检查过nginx,是通过ip_hash进行转发的啊,迷惑不解之际,公司的运维一语破的,原来公司是采用双线路由器的。于是猜测,是否因为存储cookie加密的key存在不同服务器上所导致。

打开微软的Session的源码,先查看SessionMiddleware中间件的代码,其中有以下的关键源码:

var cookieValue = context.Request.Cookies[_options.CookieName];
var sessionKey = CookieProtection.Unprotect(_dataProtector, cookieValue, _logger);
if (string.IsNullOrWhiteSpace(sessionKey) || sessionKey.Length != SessionKeyLength)
{
// No valid cookie, new session.
var guidBytes = new byte[];
CryptoRandom.GetBytes(guidBytes);
sessionKey = new Guid(guidBytes).ToString();
cookieValue = CookieProtection.Protect(_dataProtector, sessionKey);
var establisher = new SessionEstablisher(context, cookieValue, _options);
tryEstablishSession = establisher.TryEstablishSession;
isNewSessionKey = true;
}
sessionKey是从客户端的cookie中解密出来的,其中CookieProtection的_dataProtector来自
_dataProtector = dataProtectionProvider.CreateProtector(nameof(SessionMiddleware));
将系统默认注入的IDataProtectionProvider扒出来:

发现IDataProtectionProvider为Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider,该IDataProtectionProvider的keyManager为
Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager。

果然不出所料,key存在单机上,打开微软的DataProtection-dev源码查看FileSystemXmlRepository中获取Key存储路径的实现:

眼尖的发现项目下面就有一个将key持久化到redis的实现:

添加相应的nuget包,修改ConfigureServices方法:
            services.AddDataProtection()
.PersistKeysToRedis(ConnectionMultiplexer.Connect(redisConnection), dataProtectionKey);
终于完美解决!在采用分布式存储session的时候,最好将dataProtectionProvider的key也进行共享,否则如果做了ip_hash负载均衡,客户端ip一变,可能负载到另外一台服务器,导致存储session的cookie数据解密不出来从而获取不到session!

asp.net core session丢失问题排查的更多相关文章

  1. IT咨询顾问:一次吐血的项目救火 java或判断优化小技巧 asp.net core Session的测试使用心得 【.NET架构】BIM软件架构02:Web管控平台后台架构 NetCore入门篇:(十一)NetCore项目读取配置文件appsettings.json 使用LINQ生成Where的SQL语句 js_jquery_创建cookie有效期问题_时区问题

    IT咨询顾问:一次吐血的项目救火   年后的一个合作公司上线了一个子业务系统,对接公司内部的单点系统.我收到该公司的技术咨询:项目启动后没有规律的突然无法登录了,重新启动后,登录一断时间后又无法重新登 ...

  2. asp.net core Session的测试使用心得及注意事项

    sp.net-core中Session是以中间件的形式注册使用的.不比asp.net中的使用,直接使用Session就行. 首先在.net-core框架中注入Session中间件,首先在Configu ...

  3. asp.net core session的使用

    Session介绍 本文假设读者已经了解Session的概念和作用,并且在传统的.net framework平台上使用过. Asp.net core 1.0好像需要单独安装,在nuget控制台,选择你 ...

  4. asp.net core session使用

    一.配置回话状态 Microsoft.AspNetCore.App metapackage 中包含的 Microsoft.AspNetCore.Session 包提供中间件来管理会话状态. 若要启用会 ...

  5. Asp.net Core Session 存储任意对象

    using Microsoft.AspNetCore.Http; using Newtonsoft.Json; public static class SessionExtensions { publ ...

  6. ASP.NET Core 使用 Redis 和 Protobuf 进行 Session 缓存

    前言 上篇博文介绍了怎么样在 asp.net core 中使用中间件,以及如何自定义中间件.项目中刚好也用到了Redis,所以本篇就介绍下怎么样在 asp.net core 中使用 Redis 进行资 ...

  7. ASP.NET Core 2 学习笔记(十一)Cookies & Session

    基本上HTTP是没有记录状态的协定,但可以通过Cookies将Request来源区分出来,并将部分数据暂存于Cookies及Session,是写网站常用的用户数据暂存方式.本篇将介绍如何在ASP.NE ...

  8. 为什么我的会话状态在ASP.NET Core中不工作了?

    原文:Why isn't my session state working in ASP.NET Core? Session state, GDPR, and non-essential cookie ...

  9. asp.net core 使用 Redis 和 Protobuf

    asp.net core 使用 Redis 和 Protobuf 前言 上篇博文介绍了怎么样在 asp.net core 中使用中间件,以及如何自定义中间件.项目中刚好也用到了Redis,所以本篇就介 ...

随机推荐

  1. 我的摸索过程之IIS下配置asp.net 的注意事项

    "在应用程序级别之外使用注册为 allowDefinition='MachineToApplication' 的节是错误的.如果在 IIS 中没有将虚拟目录配置为应用程序,则可能导致此错误. ...

  2. PyCharm导入pymysql包运行报错问题解决:No module named 'PyMySQL'

    import pymysql # 导入包 # 报错问题显示: ImportError: No module named 'PyMySQL' 出现该问题提示:找不到该包名. 解决办法如下: ①先下载Py ...

  3. RHEL7.0 Docker离线安装以及实战笔记

    1.概述 最近在琢磨一个事--在RHEL 7.0系统上离线安装使用Docker.然后配置JAVAEE环境,发布Web服务.在网上查了资料,大多数是在线安装的,其他的要么是环境不同,要么资料包找不到了. ...

  4. Linux下DB2数据库安装教程

    最近因为工作需要在学习DB2数据库,本教程讲解DB2数据库在inux下的安装步骤. 安装前请查看 DB2版本和许可证 说明来增加了解,先弄明白改安装什么版本,这里我用的是最新的Express-C版本, ...

  5. 自己用 Netty 实现一个简单的 RPC

    目录: 需求 设计 实现 创建 maven 项目,导入 Netty 4.1.16. 项目目录结构 设计接口 提供者相关实现 消费者相关实现 测试结果 总结 源码地址:github 地址 前言 众所周知 ...

  6. java8完全解读二

    继续着上次的java完全解读一 继续着上次的java完全解读一1.强大的Stream API1.1什么是Stream1.2 Stream操作的三大步骤1.2.1 创建Stream1.2.2 Strea ...

  7. 常用域名记录解释:A记录、MX记录、CNAME记录、TXT记录、AAAA记录、NS记录

    A记录 A记录是用来创建到IP地址的记录. A记录设置技巧 1.如果想创建不带www的记录,即ezloo.com,在主机记录中填写@或者留空,不同的注册商可能不一样. 2.创建多个域名到同一个IP,比 ...

  8. Java核心卷笔记(一)

    第三章Java基程序设计结构 1.注释 三种注释方式: // 注释单行 /* 内容 */ 注释单行 /** * 内容 */ 2. java 数据类型 Java数据类型可分为两种:基本数据类型和引用数据 ...

  9. 我的Python之旅第二天

    一 .字符串操作 1单引号('').双引号("").三引号(""" """)的区别. 如果字符串中不包含单引号.双引号, ...

  10. git进阶

    一.刚提交的代码,发现需要微调一下 刚刚最新提交了一段代码,然后跟前端说,接口好了.过了2分钟,前端跟你说,哎,兄弟,那个金额能不能返回整数,不要小数点. 这个时候一般我们通常会修改一下之后,再提交一 ...