集群环境下,你不得不注意的ASP.NET Core Data Protection 机制
引言
最近线上环境遇到一个问题,就是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 机制的更多相关文章
- weblogic 12C集群环境下的session复制
做过weblogic集群环境的人应该都清楚,要想实现session同步,必须满足两个条件:第一,在weblogic.xml里面增加session同步相关的代码:第二,所有放入session的类都要序列 ...
- 在Hadoop1.2.1分布式集群环境下安装hive0.12
在Hadoop1.2.1分布式集群环境下安装hive0.12 ● 前言: 1. 大家最好通读一遍过后,在理解的基础上再按照步骤搭建. 2. 之前写过两篇<<在VMware下安装Ubuntu ...
- Ubuntu14(64位) 集群环境下安装Hadoop2.4
经过前边的积累,今天最终实现了集群环境下部署Hadoop.并成功执行了官方的样例. 工作例如以下: 两台机器: NameNode:上网小本,3G内存.机器名:YP-X100e,IP:192.168.1 ...
- 在tomcat集群环境下redis实现分布式锁
上篇介绍了redis在集群环境下如何解决session共享的问题.今天来讲一下如何解决分布式锁的问题 什么是分布式锁? 分布式锁就是在多个服务器中,都来争夺某一资源.这时候我们肯定需要一把锁是不是 , ...
- Oracle RAC 集群环境下日志文件结构
Oracle RAC 集群环境下日志文件结构 在Oracle RAC环境中,对集群中的日志的定期检查是必不可少的.通过查看集群日志,可以早期定位集群环境中出现的问题,以便将问题消灭在萌芽状态.简单介绍 ...
- CAS服务器集群和客户端集群环境下的单点登录和单点注销解决方案
CAS的集群环境,包括CAS的客户应用是集群环境,以及CAS服务本身是集群环境这两种情况.在集群环境下使用CAS,要解决两个问题,一是单点退出(注销)时,CAS如何将退出请求正确转发到用户sessio ...
- 分布式集群环境下,如何实现session共享一(应用场景)
在web应用中,由于http的请求响应式,无状态.要记录用户相关的状态信息,比如电商网站的购物车,比如用户是否登录等,都需要使用session.我们知道session是由servlet容器创建和管理, ...
- 分布式集群环境下,如何实现session共享五(spring-session+redis 实现session共享)
这是分布式集群环境下,如何实现session共享系列的第五篇.在上一篇:分布式集群环境下,如何实现session共享四(部署项目测试)中,针对nginx不同的负载均衡策略:轮询.ip_hash方式,测 ...
- 分布式集群环境下,如何实现session共享四(部署项目测试)
这是分布式集群环境下,如何实现session共享系列的第四篇.在上一篇:分布式集群环境下,如何实现session共享三(环境搭建)中,已经准备好了相关的环境:tomcat.nginx.redis.本篇 ...
随机推荐
- 原创|我是如何从零学习开发一款跨平台桌面软件的(Markdown编辑器)
原始冲动 最近一直在学习 Electron 开发桌面应用程序,目的是想做一个桌面编辑器,虽然一直在使用Typore这款神器,但无奈Typore太过国际化,在国内水土不服,无法满足我的一些需求. 比如实 ...
- LinearLayout适配不同机型技巧
<View android:layout_width="match_parent" android:layout_height="0dp" android ...
- Android的系统框架的深入认识
Android采用层次化系统架构,官方公布的标准架构如下图所示.Android由底层往上分为4个主要功能层,分别是linux内核层(Linux Kernel),系统运行时库层(Libraries和An ...
- 2019-10-29:渗透测试,基础学习,sqlmap文件读取,写入,dnslog盲注作用,mssql手工注入,笔记
sqlmap参数--file-read,从数据库服务器中读取文件--file-write,--file-dest,把文件上传到数据库服务器中 dnslog平台的学习和它在盲注中的应用1,判断注入点2, ...
- 03_Matplotlib的基本使用
python利用Matplotlib.pyplot库绘制不同的图形,但是在显示中文时存在部分问题,一般在导入库后,添加如下代码: # 设置中文正常显示 plt.rcParams['font.sans- ...
- 如何用 Python 写一个简易的抽奖程序
不知道有多少人是被这个头图骗进来的:) 事情的起因是这样的,上周有同学问小编,看着小编的示例代码敲代码,感觉自己也会写了,如果不看的话,七七八八可能也写的出来,但是一旦自己独立写一段程序,感觉到无从下 ...
- 请问1^x+2^x+3^x+\cdots +n^x的算式是什么呢?
目录 总结 请问\(1^x+2^x+3^x+\cdots +n^x\)的算式是什么呢? 一.求和式\(\sum\limits_{i=1}^n{i}\)的算式 如何证明求和简式\(\sum_{i=1}^ ...
- alloc 和 init都做了什么验证。
结论: alloc负责分配内存和创建对象对应的isa指针: init只是返回alloc生成的对象. 所以alloc后,多次调用init,返回的对象是同一个! 代码如下: // // main.m / ...
- 【开发者portal在线开发插件系列三】字符串 及 可变长度字符串
基础篇 基础场景见上面两个帖子,这里单独说明字符串和可变长度字符串的用法. 话不多说,开始今天的演(表)示(演) Profile和插件开发 添加一个string类型的属性: 在插件里添加一条数据上报消 ...
- 1.flask基础
1.flask和django的区别? flask,是一个轻量级的框架,内置了:路由/视图/模板(jinja2)/cookie/session/中间件. 可扩展强,第三方组件非常多,例如:wtforms ...