引言

最近线上环境遇到一个问题,就是ASP.NET Core Web应用在单个容器使用正常,扩展多个容器无法访问的问题。查看容器日志,发现以下异常:

System.Security.Cryptography.CryptographicException: The key {efbb9f35-3a49-4f7f-af19-0f888fb3e04b} was not found in the key ring.
2019-09-30T18:34:55.473037193+08:00 at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.UnprotectCore(Byte[] protectedData, Boolean allowOperationsOnRevokedKeys, UnprotectStatus& status)
2019-09-30T18:34:55.473046762+08:00 at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.DangerousUnprotect(Byte[] protectedData, Boolean ignoreRevocationErrors, Boolean& requiresMigration, Boolean& wasRevoked)
2019-09-30T18:34:55.473055477+08:00 at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.Unprotect(Byte[] protectedData)
2019-09-30T18:34:55.473064427+08:00 at Microsoft.AspNetCore.Session.CookieProtection.Unprotect(IDataProtector protector, String protectedText, ILogger logger)

通过排查,发现了是由于 ASP.NET Core Data Protection 机制引起的。

Data Protection 机制

对于Data Protection机制,晓东大大已经有系列文章详述了,我这里就不再过多赘述,只简单总结一下。需要了解详细的机制,建议阅读以下系列文章:

ASP.NET Core 数据保护(Data Protection)【上】

ASP.NET Core 数据保护(Data Protection)【中】

ASP.NET Core 数据保护(Data Protection 集群场景)【下】

Data Protection(数据安全)机制:为了确保Web应用敏感数据的安全存储,该机制提供了一个简单、基于非对称加密改进的、性能良好的、开箱即用的加密API用于数据保护。

它不需要开发人员自行生成密钥,它会根据当前应用的运行环境,生成该应用独有的一个私钥。这在单一部署的情况下没有问题。

一旦在集群环境下进行水平扩展,那么每个独立的应用都有一个独立的私钥。这样在负载均衡时,一个请求先在A容器建立的Session会话,该机制会通过当前容器的密钥加密Cookie写入到客户端,下个请求路由到B容器,携带的Cookie在B容器是无法通过B容器的密钥进行解密。

进而会导致会话信息丢失的问题。所以在集群情况下,为了确保加密数据的互通,应用必须共享私钥

私钥共享

这里以使用Redis来共享私钥举例,添加Microsoft.AspNetCore.DataProtection.StackExchangeRedis Nuget包用于存储密钥。

添加Microsoft.Extensions.Caching.StackExchangeRedisNuget包用于配置分布式Session。

public IServiceProvider ConfigureServices(IServiceCollection services)
{ //获取Redis 连接字符串
var redisConnStr = this.Configuration.GetValue<string>(SigeAppSettings.Redis_Endpoint);
var redis = ConnectionMultiplexer.Connect(redisConnStr);//建立Redis 连接 //添加数据保护服务,设置统一应用程序名称,并指定使用Reids存储私钥
services.AddDataProtection()
.SetApplicationName(Assembly.GetExecutingAssembly().FullName)
.PersistKeysToStackExchangeRedis(redis, "DataProtection-Keys"); //添加Redis缓存用于分布式Session
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = redisConnStr;
options.InstanceName =Assembly.GetExecutingAssembly().FullName;
}); //添加Session
services.AddSession(options =>
{
options.Cookie.Name = Assembly.GetExecutingAssembly().FullName;
options.IdleTimeout = TimeSpan.FromMinutes(20);//设置session的过期时间
options.Cookie.HttpOnly = true;//设置在浏览器不能通过js获得该cookie的值
options.Cookie.IsEssential = true;
}
);
}

集群环境下,你不得不注意的ASP.NET Core Data Protection 机制的更多相关文章

  1. weblogic 12C集群环境下的session复制

    做过weblogic集群环境的人应该都清楚,要想实现session同步,必须满足两个条件:第一,在weblogic.xml里面增加session同步相关的代码:第二,所有放入session的类都要序列 ...

  2. 在Hadoop1.2.1分布式集群环境下安装hive0.12

    在Hadoop1.2.1分布式集群环境下安装hive0.12 ● 前言: 1. 大家最好通读一遍过后,在理解的基础上再按照步骤搭建. 2. 之前写过两篇<<在VMware下安装Ubuntu ...

  3. Ubuntu14(64位) 集群环境下安装Hadoop2.4

    经过前边的积累,今天最终实现了集群环境下部署Hadoop.并成功执行了官方的样例. 工作例如以下: 两台机器: NameNode:上网小本,3G内存.机器名:YP-X100e,IP:192.168.1 ...

  4. 在tomcat集群环境下redis实现分布式锁

    上篇介绍了redis在集群环境下如何解决session共享的问题.今天来讲一下如何解决分布式锁的问题 什么是分布式锁? 分布式锁就是在多个服务器中,都来争夺某一资源.这时候我们肯定需要一把锁是不是 , ...

  5. Oracle RAC 集群环境下日志文件结构

    Oracle RAC 集群环境下日志文件结构 在Oracle RAC环境中,对集群中的日志的定期检查是必不可少的.通过查看集群日志,可以早期定位集群环境中出现的问题,以便将问题消灭在萌芽状态.简单介绍 ...

  6. CAS服务器集群和客户端集群环境下的单点登录和单点注销解决方案

    CAS的集群环境,包括CAS的客户应用是集群环境,以及CAS服务本身是集群环境这两种情况.在集群环境下使用CAS,要解决两个问题,一是单点退出(注销)时,CAS如何将退出请求正确转发到用户sessio ...

  7. 分布式集群环境下,如何实现session共享一(应用场景)

    在web应用中,由于http的请求响应式,无状态.要记录用户相关的状态信息,比如电商网站的购物车,比如用户是否登录等,都需要使用session.我们知道session是由servlet容器创建和管理, ...

  8. 分布式集群环境下,如何实现session共享五(spring-session+redis 实现session共享)

    这是分布式集群环境下,如何实现session共享系列的第五篇.在上一篇:分布式集群环境下,如何实现session共享四(部署项目测试)中,针对nginx不同的负载均衡策略:轮询.ip_hash方式,测 ...

  9. 分布式集群环境下,如何实现session共享四(部署项目测试)

    这是分布式集群环境下,如何实现session共享系列的第四篇.在上一篇:分布式集群环境下,如何实现session共享三(环境搭建)中,已经准备好了相关的环境:tomcat.nginx.redis.本篇 ...

随机推荐

  1. 20191010-6 alpha week 1/2 Scrum立会报告+燃尽图 04

    此作业的要求参见[https://edu.cnblogs.com/campus/nenu/2019fall/homework/8749] 一.小组情况 队名:扛把子 组长:迟俊文 组员:宋晓丽 梁梦瑶 ...

  2. SpringCloud Alibaba微服务实战 - 基础环境准备

    Springcloud Aibaba现在这么火,我一直想写个基于Springcloud Alibaba一步一步构建微服务架构的系列博客,终于下定决心从今天开始本系列文章的第一篇 - 基础环境准备. 该 ...

  3. python与redis交互及redis基本使用

    Redis简介 Redis是一使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日个开源的志型.Key-Value数据库,并提供多种语言的API. 从2010年3月15日起,Redis的开发工 ...

  4. 关于vue中的videoPlayer的src视频地址参数动态修改(网上一堆错误方法,被误导很久,自己找到了正确的方法,供大家借鉴)

    方法很简单:相信大家的问题应该是改变src的值吧,动态赋值这一步简单.this.playerOptions['sources'][0]['src'] 就是这一步解决提取src问题,主要部分用绿色框起来 ...

  5. Java多线程面试题:线程锁+线程池+线程同步等

    1.并发编程三要素? 1)原子性 原子性指的是一个或者多个操作,要么全部执行并且在执行的过程中不被其他操作打断,要么就全部都不执行. 2)可见性 可见性指多个线程操作一个共享变量时,其中一个线程对变量 ...

  6. Rust 入门 (四)

    所有权是 rust 语言独有的特性,它保证了在没有垃圾回收机制下的内存安全,所以理解 rust 的所有权是很有必要的.接下来,我们来讨论所有权和它的几个特性:借用.切片和内存结构. 什么是所有权 Ru ...

  7. 【ASP.NET Core学习】Web API

    这里介绍在ASP.NET Core中使用Web API创建 RESTful 服务,本文使用VSCode + NET Core3.0 创建简单Rest API 格式化输出 JSON Patch请求 Op ...

  8. mysql那些事(3)小数如何存储

    创建mysql数据表的时候,经常会遇到存储小数(浮点数)的情况,如:价格,重量,身高等. 目前大的公司流行三种存储方案: 1.将数据扩大10的倍数达到使用整数类型存储目的. 比如价格,我们经常以分为单 ...

  9. Spring源码学习笔记之bean标签属性介绍及作用

    传统的Spring项目, xml 配置bean在代码中是经常遇到, 那么在配置bean的时候,这些属性的作用是什么呢? 虽然说现在boot项目兴起,基于xml配置的少了很多, 但是如果能够了解这些标签 ...

  10. luogu P3152 正整数序列

    题目描述 kkk制造了一个序列,这个序列里的数全是由正整数构成的.你别认为她的数列很神奇--其实就是1, 2, -, n而已.当然,n是给定的.kkk的同学lzn认为0是一个好数字(看上去很饱满有木有 ...