最近公司采用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. html5中新增的非主体结构的元素

    html5中出了新增了article.section.nav.aside.time主要结构元素外,还增加了一些表示逻辑结构或附加信息的非主体结构元素. 一.header元素 header元素是一种具有 ...

  2. 使用swagger管理接口

    swagger 配置 1.pom 增加jar包依赖 <dependency> <groupId>io.springfox</groupId> <artifac ...

  3. dp,px,pt,sp 的区别 以及dp 和 px 互转

    dp = dip : device independent pixels(设备独立像素). 不同设备有不同的显示效果,这个和设备硬件有关,一般我们为了支持WVGA.HVGA和QVGA 推荐使用这个,不 ...

  4. (linux虚拟机)克隆得到的虚拟机修改网卡信息和IP地址,以及DNS

    克隆得到的虚拟机,与原先的系统是一模一样的包括MAC地址和IP地址.需要修改成信息. 克隆完事之后,首先在 点击生成一个新的MAC地址.然后启动,登陆. vim /etc/udev/rules.d/7 ...

  5. SQL Server Agent Job 多服务器管理

  6. ASP.NET(C#) Repeater分页的实现

    ASP.NET(C#) Repeater分页的实现 第一种方式: 数据库连接代码: using System; using System.Data; using System.Configuratio ...

  7. Flask入门之flask-wtf表单处理

    参考文章 1. 使用 WTForms 进行表单验证  第11集 #Sample.py # coding:utf-8 from flask import Flask,render_template,re ...

  8. mysql学习 第二章 数据库的基本操作

    3.1   创建数据库 MySQL安装好之后,首先需要创建数据库,这是使用MySQL各种功能的前提.本章将详细介绍数据的基本操作,主要内容包括:创建数据库.删除数据库.不同类型的数据存储引擎和存储引擎 ...

  9. Maven Scope 依赖范围

    Maven依赖范围就是用来控制依赖与这三种classpath(编译classpath.测试classpath.运行classpath)的关系,Maven有以下几种依赖范围: ·compile:编译依赖 ...

  10. 导出excel记录

    前言: 记录这篇使用记录,是为了方便以后学习查阅和让没有使用过的人了解一下,其中不足还请见谅.不是很全的文章,大神请绕行. 在项目中我们或多或少的会遇到数据导出到excel表格以便线下查看或者记录一些 ...