扩展IdentityServer4服务

我遵循IdentityServer4快速入门,并且能够使用隐式授权对IdentityServer的localhosted实例进行身份验证(与快速入门中提供的几乎相同)。 同样,我的IdentityServer与上面提到的快速入门中提供的几乎完全相同 - 它只是具有一些自定义用户详细信息。

然后,我将应用程序(C#.NET Core)移动到Docker容器中,并在Kubernetes集群(单个实例)中托管了一个这样的实例,并创建了一个Kubernetes服务(通过一个或多个“真实”服务实现)群集外部的身份服务器。 我可以修改我的JavaScript网页并将其指向我的Kubernetes服务,它仍然很高兴地显示登录页面,并且它似乎按预期工作。

然后,当我将IdentityServer扩展为三个实例(全部服务于单个Kubernetes服务后)时,我开始遇到问题。 Kubernetes服务向每个身份服务器发出请求,因此第一个会显示登录页面,但第二个会在按下登录按钮后尝试并处理身份验证。 这会导致以下错误:

System.InvalidOperationException:防伪令牌无法解密。 ---> System.Security.Cryptography.CryptographicException:在密钥环中未找到密钥{19742e88-9dc6-44a0-9e89-e7b09db83329}。 在Microsoft.AspNetCore.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.UnprotectCore(Byte [] protectedData,Boolean allowOperationsOnRevokedKeys,UnprotectStatus&status)在Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.DangerousUnprotect(Byte [] protectedData,Boolean ignoreRevocationErrors,Boolean&requiresMigration,Boolean&wasRevoked )在Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.Unprotect(Byte [] protectedData)在Microsoft.AspNetCore.Antiforgery.Internal.DefaultAntiforgeryTokenSerializer.Deserialize(String serializedToken)---结束内部异常堆栈跟踪--- ...还有更多......

所以 - 我知道我得到这个错误,因为期望是相同的IdentityServer应该为它显示的页面提供请求服务(否则反伪造令牌如何工作,对吧?),但是我想要的是什么理解是我可以如何在复制环境中完成这项工作。

我不想在不同的IP /端口上托管多个身份服务器; 我试图建立一个HA配置,如果一个IdentityServer死了,没有任何调用端点应该关心(因为请求应该由其他工作实例服务)。

我说我使用的是快速启动代码 - 这意味着在IdentityServer的启动中,有代码看起来像这样...

    public void ConfigureServices(IServiceCollection services)  
    {
        services.AddMvc();

        services.AddIdentityServer(options =>
            {
                options.Events.RaiseSuccessEvents = true;
                options.Events.RaiseFailureEvents = true;
                options.Events.RaiseErrorEvents = true;
            })
            .AddTemporarySigningCredential()
            .AddInMemoryIdentityResources(Config.GetIdentityResources())
            .AddInMemoryApiResources(Config.GetApiResources())
            .AddInMemoryClients(Config.GetClients())

我假设我需要用一个证书替换.AddTemporarySigningCredential()逻辑,该证书可以被运行在我的Kubernetes集群中的IdentityServer的所有实例使用。 不知道MVC是如何工作的(MVC6用于在IdentityServer服务中生成登录页面,我从上面的示例代码链接中获得) - 我想知道是否只是更改代码以使用共享的正确证书所有服务都足以让原型HA IdentityServer集群正常工作?

通过工作,我的意思是,我的期望是,我可以在Kubernetes集群中运行n个IdentityServer实例,让Kubernetes服务充当我正在运行的许多IdentityServer的外观,并且能够使用多个IdentityServer实例进行身份验证它们可以共享数据,以至于它们都为我的调用Web应用程序提供完全相同的权限,并且可以在一个或多个实例死亡的情况下处理彼此的请求。

任何帮助或见解将不胜感激。


我想我已经解决了这个问题。 为了解决我的问题,我做了两件事:

  • 创建我自己的X509证书并在我的每个IdentityServer之间共享此证书。 有很多关于如何在网络上创建有效证书的例子; 我刚刚用过
    services.AddIdentityServer(...).AddSigningCredential(new X509Certificate2(bytes, "password")在我的启动类中。
  • 深入研究MVC框架代码,并发现我需要实现一个密钥存储提供程序,以便在提供登录页面的Identity Server的MVC部分的不同实例之间共享状态。
  • 事实证明,NuGet提供了一个由Redis提供支持的KSP,这意味着我只需要在我的Kube集群中启动一个私有Redis实例(无法在群集外访问)以共享解密秘密。

    /* Note: Use an IP, or resolve from DNS prior to adding redis based key store as direct DNS resolution doesn't work for this inside a K8s cluster, though it works quite happily in a Windows environment. */
    var redis = ConnectionMultiplexer.Connect("1.2.3.4:6379"); services.AddDataProtection() .PersistKeysToRedis(redis, "DataProtection-Keys");

    我现在可以将我的身份服务扩展为3个实例,并将Kube服务作为所有可用实例的外观。 我可以将日志视为身份服务之间的Kubernetes round-robin请求,并且我的身份验证正如我所期望的那样发生。

    感谢那些在这篇文章之前对这个问题发表评论的人。

    链接地址: http://www.djcxy.com/p/39953.html

    上一篇: Scaling an IdentityServer4 service

    下一篇: File (s) not on client