首页 > 解决方案 > 无法让分布式缓存与 Identity Server 一起使用

问题描述

我已经按照 MSDN中的建议介绍了使用 DB 的分布式缓存。目的是让我们的 IDP 服务器在 Kubernetes 上的多个 pod 上工作。在Startup.cs中,我像这样添加服务。

services.AddDistributedSqlServerCache(options =>
{
    options.ConnectionString = Configuration.GetConnectionString("DbTarget");
    options.ExpiredItemsDeletionInterval = new TimeSpan(10, 0, 0);
    options.SchemaName = "dbo";
    options.TableName = "Pokemons";
});
services.AddAuthorization(options => ... );
services.AddDbContext<AppDbContext>(ContextOptions());
services.AddIdentity<AppUser, AppRole>()
    .AddEntityFrameworkStores<AppDbContext>();

我检查了数据库,可以确认有一个与我们的选项相对应的表。但是,它是空的,因此目前没有可用的分布式缓存信息。根据this,我应该请求IDS4的默认存储,我尝试通过以下代码来完成。(我没有使用AddOpenIdConnect(...)but AddIdentityServerAuthentication(...)。但是,由于 IDS4 遵循 OIDC 标准,因此我认为它已包含在内。)

services.AddIdentityServer(Ids4Options())
    .AddAspNetIdentity<AppUser>()
    .AddOperationalStore(OperationOptions())
    .AddConfigurationStore(ConfigOptions())
    .AddProfileService<ProfileService>()
    .AddDeveloperSigningCredential();

services.ConfigureApplicationCookie(options =>
{
    options.ExpireTimeSpan = TimeSpan.FromSeconds(55);
    options.SlidingExpiration = false;
});

services.AddHealthChecks();
services.AddCors(...);

services.AddOidcStateDataFormatterCache();
services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
    .AddIdentityServerAuthentication(options =>
     {
         options.Authority = Configuration["Env:BaseUrl"];
     });

我预计如果分布式缓存生效并设置了数据格式化程序,我的数据库中的表将在登录时被填充。但这不会发生。测试在构造函数中使用 DI 访问缓存是可行的,当我执行类似这样的操作时,我会看到数据库中的条目

public MyClass (IDistributedCache cache) { Cache = cache; }
...
byte[] data = Encoding.ASCII.GetBytes("roo");
await Cache.SetAsync("kanga", data);

GitHub 上有一个问题,建议明确指定模式,如下所示。遗憾的是,这并没有改变我的情况。

service.AddOidcStateDataFormatterCache(
  IdentityServerAuthenticationDefaults.AuthenticationScheme)

HttpContext.SignInAsync()当我在本地执行项目时,在验证用户凭据有效后调用时,我会看到存储在浏览器的应用程序选项卡中的两个 cookie 。我期待与这些相对应的东西也将存储在数据库中。我的同事们提出了关于切换到 SingalR 的建议。但是,我看不出将 chache 提供程序更改为 Redis 等将如何解决任何问题,因为问题不是负载,而是不存在存储的信息。我还验证了这张桌子dbo.PersistedGrants是活跃的,充满了价值观。努力证明的冰山一角:无关的、风滚草的、理论上的、已经实施的. 基于搜索键的其他建议中的相同主题。

显然,缺少启用分布式登录的附加步骤。或者,可能,我做错了什么。目前,我没有其他线索(尽管进行了广泛的谷歌搜索),并且由于缺乏解决问题或进一步调查的想法而陷入困境。

标签: c#cachingidentityserver4distributed-caching

解决方案


我设法解决了它,有很多脏话和汗水。第一个提示来自这个答案,表明我正在使用的证书在多 pod 环境中不可行。请注意,以前版本的 .NET 应用了不同的方法(AddTestCredential()或类似的方法),该方法现在已经过时,取而代之的是下面的方法。

services. ...
  //.AddDeveloperSigningCredential();
  .AddSigningCredential(cert);

有关于如何创建证书文件的博客。它可能会涉及很多黑魔法,例如创建和转换文件、复合子证书、选择域等。它既复杂又困难。我的建议是 - 关注博客并希望获得最好的结果。证书最终可以通过下面的简单代码或使用提供证书密钥的服务来分发。

string path = base + "/certificate.pfx";
string pass = Configuration.GetValue<string>(...);
X509Certificate2 cert = new X509Certificate2(path, pass);

一旦我们做到了(指的是和我一起骑着霰弹枪的同事),一切都开始按预期运行。问题显然不在于分布式缓存,而在于访问它,因为使用AddDeveloperSigningCredential().

在我看来,这应该更加明显和有据可查。一些要检查的资源(没有声称是完整的)来这里。


推荐阅读