ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Orchard Core 数据保护实战指南:多租户与负载均衡环境下的密钥持久化方案

Orchard Core 数据保护实战指南:多租户与负载均衡环境下的密钥持久化方案 CMS后端Web框架【免费下载链接】OrchardCoreOrchard Core is an open-source modular and multi-tenant application framework built with ASP.NET Core, and a content management system (CMS) built on top of that framework.项目地址https://gitcode.com/gh_mirrors/or/OrchardCore点击查看免费下载导读本文围绕 Orchard Core 的数据保护Data Protection机制展开重点讲解在**多租户Multi-tenant与负载均衡Load-balanced**部署环境下如何通过Azure Blob Storage与Redis两种分布式方案持久化并共享数据保护密钥Key Ring并深入剖析其源码级实现原理与配置细节。读完本文你将掌握数据保护密钥的本地存储机制、两种分布式存储方案的完整配置步骤、密钥隔离策略以及生产环境下的持久化注意事项。概述什么是 Orchard Core 数据保护数据保护是 ASP.NET Core 提供的一项关键安全机制。Orchard Core 基于 ASP.NET Core 构建天然继承了这一机制并利用它保护以下敏感数据身份验证 CookieAuthentication Cookies用户登录会话的加密凭据防伪令牌Anti-Forgery Tokens防止跨站请求伪造CSRF攻击需要解密持久化的密钥Persisted Secrets例如 SMTP 密码注意不包含用户密码用户密码使用独立的哈希机制存储临时数据Temporary Data如临时存储的中间状态。在 Orchard Core 中每个租户Tenant拥有相互隔离的数据保护密钥环。系统通过PersistKeysToFileSystem(directory)将密钥持久化到App_Data目录下该租户专属的文件夹中例如App_Data/Sites/Default/DataProtection-Keys。相关实现位于 src/OrchardCore/OrchardCore/Modules/Extensions/ServiceCollectionExtensions.cs 的AddDataProtection方法中。从源码可以看到租户级数据保护的核心逻辑是基于ShellSettings获取当前租户名称settings.Name将密钥目录定位到App_Data/Sites/{TenantName}/DataProtection-Keys调用.PersistKeysToFileSystem(directory)将密钥环写入该目录通过.SetApplicationName(settings.Name)将应用名设置为租户名确保不同租户之间无法互相解密对方的数据。这种开箱即用的本地存储方案无需任何配置即可工作是单服务器部署的默认选择。然而在分布式场景下它存在明显局限。为什么需要分布式数据保护在单服务器部署中数据保护密钥默认存储在本地文件系统。但这种方式在以下场景会引发严重问题负载均衡环境Load-balanced environments每个服务器持有各自的密钥环。当请求被路由到不同服务器时服务器 A 加密的 Cookie 无法被服务器 B 解密导致身份验证间歇性失败多租户设置Multi-tenant setups每个租户需要隔离但持久的密钥存储。若密钥只存在单机磁盘上迁移或扩展节点时密钥无法共享应用重启Application restarts本地存储的密钥可能丢失例如容器化部署中文件系统不持久导致已签发的 Cookie 与令牌全部失效用户被迫重新登录。分布式数据保护的解决方案是将密钥环存储在一个或多个所有应用实例都可访问的共享位置。Orchard Core 提供了以下选项方案存储位置特点适用场景本地存储默认App_Data/Sites/{Tenant}/DataProtection-Keys零配置开箱即用单服务器、开发环境Azure Blob StorageAzure Blob 容器云原生、按租户自动隔离云部署、负载均衡RedisRedis 键空间低延迟、高性能已有 Redis 基础设施、对延迟敏感完整文档见 Data Protection 指南。接下来重点讲解两种分布式方案。方案一Azure Blob Storage 数据保护Azure 数据保护模块OrchardCore.DataProtection.Azure允许将数据保护密钥环存储在 Azure Blob Storage 容器中并自动按租户隔离密钥。这在负载均衡部署中尤为重要——所有活跃实例必须访问同一个密钥环才能正常工作。前置条件一个 Azure 存储账户Storage Account该模块对应的功能Feature在租户中启用在appsettings.json或任何IShellConfiguration能读取的配置源中配置连接字符串。基本配置模块通过IShellConfiguration读取配置。最简单的做法是更新appsettings.json{ OrchardCore: { OrchardCore_DataProtection_Azure: { ConnectionString: DefaultEndpointsProtocolhttps;AccountNamemyaccountname;AccountKeymyaccountkey;EndpointSuffixcore.windows.net, ContainerName: dataprotection, BlobName: , CreateContainer: true } } }配置项说明配置项说明默认值ConnectionStringAzure 存储账户连接字符串必填无ContainerNameAzure Blob 容器名称。必须是合法的 DNS 名称符合 Azure 容器命名规则例如只能小写dataprotectionBlobName存储密钥的具体 Blob 名称可选。未提供时默认使用按租户的文件夹路径租户专属路径Sites/{Tenant}/DataProtectionKeys.xmlCreateContainer容器不存在时是否自动创建true在默认配置下所有租户的数据保护密钥存储在同一容器中按每个租户一个文件夹的方式组织dataprotection/Sites/tenant_name/DataProtectionKeys.xml在Startup阶段若CreateContainer为true模块会检查容器是否存在不存在则自动创建若容器已存在可将其设为false跳过检查。源码实现细节从 Startup.cs 可以看到模块的启动逻辑通过_configuration.GetValuestring(OrchardCore_DataProtection_Azure:ConnectionString)读取连接字符串若连接字符串为空模块会输出 Critical 级别日志并直接跳过注册不会抛出异常中断应用若配置存在会先services.RemoveAllIConfigureOptionsKeyManagementOptions()移除此前注册的密钥管理配置包括默认的本地文件系统方案再调用AddDataProtection().PersistKeysToAzureBlobStorage(...)注册 Azure Blob 存储为密钥仓库同时注册BlobOptionsConfiguration与BlobModularTenantEvents租户事件负责容器初始化。而 BlobOptionsConfiguration.cs 负责解析配置使用IShellConfiguration.Bind(OrchardCore_DataProtection_Azure, options)绑定配置ConfigureContainerName中通过 Fluid 模板解析ContainerName并强制ToLowerInvariant()Azure 容器名只允许小写若CreateContainer为true通过BlobContainerClient.CreateIfNotExistsAsync(PublicAccessType.None)以私有访问权限自动创建容器ConfigureBlobName中若未显式指定BlobName则默认生成{ShellsContainerName}/{TenantName}/DataProtectionKeys.xml即每个租户一个文件夹的结构。进阶配置Liquid 模板化模块支持使用Liquid 模板进一步定制配置。模板中可以访问ShellSettings对象即当前租户的设置。只有ContainerName和BlobName两个属性支持模板化。若未提供BlobName会自动默认为按租户的文件夹路径Sites/tenant_name/DataProtectionKeys.xml。⚠️注意使用{{ ShellSettings.Name }}模板化ContainerName时租户名会被自动转换为小写。但你仍需确保ContainerName符合 Azure Blob 命名规范见 Azure 官方文档。⚠️注意模板解析期间只有默认的 Liquid 过滤器与标签可用额外的过滤器如slugify不可用。配置每个租户一个容器如需更细粒度的隔离可以为每个租户配置独立的容器{ OrchardCore: { OrchardCore_DataProtection_Azure: { ConnectionString: DefaultEndpointsProtocolhttps;AccountNamemyaccountname;AccountKeymyaccountkey;EndpointSuffixcore.windows.net, ContainerName: {{ ShellSettings.Name }}-dataprotection, BlobName: {{ ShellSettings.Name }}DataProtectionKeys.xml, CreateContainer: true } } }这样每个租户拥有独立的容器与 Blob实现更强的密钥隔离粒度。方案二Redis 数据保护Redis 模块OrchardCore.Redis提供OrchardCore.Redis.DataProtection功能允许将数据保护密钥存储在 Redis 中为分布式应用提供高性能的密钥共享方案尤其适合对低延迟密钥访问有要求的负载均衡环境。前置条件在配置 Redis 数据保护之前请确保有一个运行中的 Redis 实例已启用OrchardCore.Redis模块已启用OrchardCore.Redis.DataProtection功能。配置步骤首先在appsettings.json中配置基础的 Redis 连接{ OrchardCore: { OrchardCore_Redis: { Configuration: your-redis-connection-string, InstancePrefix: MyApp:, AllowAdmin: true } } }配置项说明配置项说明默认值ConfigurationRedis 连接字符串必填无InstancePrefix添加到所有 Redis 键上的前缀可选无AllowAdmin是否允许执行管理员命令可选false补充说明源自 Redis 模块 Startup.cs 的解析逻辑若Configuration缺失或无效模块会记录错误日志且 Redis 相关功能在该租户上不激活还支持一个额外的DisableCertificateVerification配置默认false。设为true时会忽略 SSL 策略错误远程证书不可用除外允许使用自签名证书的 Redis 服务器AllowAdmin会映射到ConfigurationOptions.AllowAdmin用于允许执行CONFIG等管理员命令。密钥存储结构Redis 数据保护使用如下模式存储密钥{InstancePrefix}{TenantName}:DataProtection-Keys例如当InstancePrefix为MyApp:、租户名为Default时密钥键为MyApp:Default:DataProtection-Keys从源码 RedisKeyManagementOptionsSetup.cs 可以看到该键由${redis.InstancePrefix}{_tenant}:DataProtection-Keys拼装而成其中_tenant来自ShellSettings.Name天然实现了按租户隔离。持久化注意事项重要警告⚠️警告数据保护密钥环不是缓存文件必须保存在持久化存储中。请确保你的 Redis 服务器配置了备份策略防止数据丢失。建议使用AOFAppend-Only File或RDBRedis Database持久化。Redis 数据保护模块会在AllowAdmin为true时自动检查持久化是否启用若未配置则记录警告日志参考 RedisKeyManagementOptionsSetup.cs 中的CheckRedisPersistenceEnabled方法通过server.Info(persistence)检查 Redis 服务器持久化配置检测aof_enabled 1或rdb_saves ! 0即认为持久化已启用若AllowAdmin为false则无法执行管理员命令模块无法检查持久化状态此时需人工确保 Redis 已配置持久化注意源码注释中的说明RDB 检查并不完全可靠它只检查 Redis 启动后是否发生过保存而非周期性的定时保存是否启用。源码实现细节升级兼容与密钥迁移RedisKeyManagementOptionsSetup.cs 中还有一个值得关注的细节Orchard Core 3.0 版本更新了 Redis 密钥格式。为避免升级期间破坏数据保护、同时不影响已运行的节点模块在发现新键不存在时会将旧格式键({InstancePrefix}{Tenant}:DataProtection-Keys注意左侧括号复制到新键并输出警告日志。该迁移逻辑位于ChangeXmlRepositoryRedisKey方法中若复制失败会记录 Error 日志但不会阻断启动。该配置类通过注册IConfigureOptionsKeyManagementOptions生效见 Redis Startup.cs 的RedisDataProtectionStartup其核心动作是确保 Redis 连接已建立redis.ConnectAsync()调用PersistKeysToRedis等价逻辑将XmlRepository设置为RedisXmlRepository键为上述拼装结果在建立连接时重新确认并迁移密钥键。方案对比与选型建议维度本地文件系统Azure Blob StorageRedis配置复杂度零配置需连接字符串 容器名需连接字符串 功能启用密钥隔离按租户目录隔离默认按租户文件夹可模板化为每租户独立容器按InstancePrefix TenantName键隔离访问延迟本地磁盘最快网络延迟HTTP网络延迟内存级较低持久化依赖 App_Data 目录持久性Azure 存储天然持久必须自行配置 AOF/RDB适用场景单机、开发环境云原生多节点部署已有 Redis 的分布式环境、低延迟需求选型建议若应用已部署在 Azure 且使用负载均衡优先选择 Azure Blob Storage密钥天然持久且按租户隔离若团队已有 Redis 基础设施缓存、总线、锁等已在用选择 Redis Data Protection 可复用基础设施、获得低延迟访问但务必确认 Redis 持久化已开启单机或开发环境无需任何配置本地存储即可满足需求。常见问题排查要点启用 Azure 数据保护后应用启动失败/日志出现 Critical检查OrchardCore_DataProtection_Azure:ConnectionString是否拼写正确、是否位于OrchardCore配置节点下。源码中该配置缺失时只会记录 Critical 日志并跳过不会阻止应用启动负载均衡下 Cookie 仍间歇性失效确认所有节点是否指向同一个Azure 容器/Redis 键空间且容器名/InstancePrefix配置一致Redis 方案重启后密钥丢失检查 Redis 是否启用了 AOF/RDB 持久化并留意模块在AllowAdmin: true时输出的持久化警告日志多租户密钥相互解密问题Orchard Core 通过.SetApplicationName(settings.Name)本地方案与InstancePrefix TenantName键隔离Redis 方案确保租户间无法互相解密升级旧版本后 Redis 密钥键变化模块已内置旧键到新键的复制迁移逻辑升级时留意 Warning 日志即可。延伸阅读Data ProtectionAzure Storage模块文档含 Liquid 模板化的完整说明Redis 模块文档含 Redis Cache / Bus / Lock 等其他分布式能力Orchard Core 配置文档了解IShellConfiguration与配置源机制相关源码Azure 模块 Startup.cs、BlobOptionsConfiguration.csRedis 模块 RedisKeyManagementOptionsSetup.cs、Startup.cs租户本地密钥注册逻辑见 ServiceCollectionExtensions.cs。赞分享CMS后端Web框架【免费下载链接】OrchardCoreOrchard Core is an open-source modular and multi-tenant application framework built with ASP.NET Core, and a content management system (CMS) built on top of that framework.项目地址https://gitcode.com/gh_mirrors/or/OrchardCore点击查看免费下载相关推荐DeepSpeech 贡献指南从高质量 Pull Request 到通过代码评审的完整实践DeepSpeech 贡献指南从高质量 Pull Request 到通过代码评审的完整实践 DeepSpeech 是一个可离线运行、支持在树莓派 4 到高性能人工智能语音音频深度学习EF Core负载均衡在多个数据库实例间分配负载EF Core负载均衡在多个数据库实例间分配负载 引言 在现代企业级应用中数据库性能往往成为系统瓶颈。当单数据库实例无法满足高并发、大数据量的业务需求时如ORM后端数据库Sunshine负载均衡多客户端支持的实现与优化Sunshine负载均衡多客户端支持的实现与优化 引言游戏串流的新挑战 在当今多设备互联的时代游戏玩家不再满足于单一设备的游戏体验。家庭中可能同时有多个成音视频后端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表