引言

最近线上环境遇到一个问题,就是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. nmap中的详细命令

    nmap全部参数详解-A 综合性扫描端口:80http 443https 53dns 25smtp 22ssh 23telnet20.21ftp 110pop3 119nntp 143imap 179 ...

  2. ubuntu windows mutual remote control

    Win10 remote control Ubuntu18 Part1.ubuntu settings 1.安装所需组件 sudo apt-get update //若没有desktop sharin ...

  3. Scala学习系列一

    一 scala介绍 Scala是一门以java虚拟机(JVM)为目标运行环境并将面向对象和函数式编程的最佳特性结合在一起的静态类型编程语言. 1)  Scala 是一门多范式 (multi-parad ...

  4. linux网络配置(ifcfg)

    将linux主机接入到网络需要配置哪些配置项? IP/NETMASK:本地通信. 路由(网管):跨网络通信. DNS服务器地址:基于主机名通信. DNS服务器有三种:主/备用DNS服务器/第三备份dn ...

  5. 在IOS中实现新浪微博OAuth认证

    主要讲解在ios中的认证流程,至于如何得到新浪用户授权账号,地址,这些可以见视频0506. 1.用UIWebView访问新浪授权页面https://api.weibo.com/oauth2/autho ...

  6. Flask入门学习——配置参数的管理方式

    一般来说有这么几种方式: 直接操作config的字典对象 app.config["DEBUG"] = True 使用配置文件加载,直接传入文件名 app.config.from_p ...

  7. Leetcode_01【两数之和】

    文章目录:  题目 脚本一及注释 脚本逻辑 脚本二及注释 脚本逻辑 题目: 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. ...

  8. Python高级用法

    Python高级用法 三元表达式 x = 10 y = 20 print(x if x > y else y) x = 100 y = 20 print(x if x > y else y ...

  9. $("#loginname").tips和jQuery中 的ajax

    jquery tips 提示插件 jquery.tips.js v0.1beta: 使用方法 $("#loginname").tips({ //#loginname为jquery的 ...

  10. 怎么把宿主机上的镜像推送到hub上

    怎么把宿主机上的镜像推送到hub上: 1.查看系统中存在的镜像: [root@izuf63bjp8ts8nkl13pxh1z devicemapper]# docker imagesREPOSITOR ...