0

我按照IdentityServer4文档使用默认测试配置(使用内存中的客户端和用户)创建了一个基本的本地实现。此时IS4初始化如下:

services.AddIdentityServer()
    .AddDeveloperSigningCredential()
    .AddInMemoryIdentityResources(Config.GetIdentityResources())
    .AddInMemoryApiResources(Config.GetApiResources())
    .AddInMemoryClients(Config.GetClients())
    .AddTestUsers(Config.GetUsers());

然后,我按照说明使用oidc-connect库创建了一个简单的 Javascript 应用程序。这很好用,所以现在我有一个 Javascript 应用程序,它允许用户通过我的 IS4 实例登录。此 JS 应用程序在 IS4 中表示为按照说明使用隐式流的客户端。

我现在想将我的 IS4 实例与我的真实用户商店集成。阅读了几篇文章后,我似乎需要根据此 SO 帖子IResourceOwnerPasswordValidator和其他各种帖子提供实现。IProfileService

我已经这样做了,现在只使用一个虚拟用户存储库,它与一组虚拟内存用户而不是真正的外部存储一起使用。我的 IS4 初始化现在看起来像这样:

services.AddIdentityServer()
    .AddDeveloperSigningCredential()
    .AddInMemoryIdentityResources(Config.GetIdentityResources())
    .AddInMemoryApiResources(Config.GetApiResources())
    .AddInMemoryClients(Config.GetClients());

builder.Services.AddTransient<IProfileService, CustomProfileService>();
builder.Services.AddTransient<IResourceOwnerPasswordValidator, CustomResourceOwnerPasswordValidator>();

现在,当我返回并测试我的 Javascript 应用程序时,这会变得很奇怪。尝试登录时,我被带到我的 IS4 登录屏幕。我输入了我希望工作的凭据,但返回了无效的用户名或密码。调试我可以看到代码永远不会进入我的ValidateAsync方法CustomResourceOwnerPasswordValidator但是,我偶然发现,如果我输入bobalice作为用户名和密码(例如,输入bob作为用户名密码)然后我通过身份验证并可以返回到我的应用程序。这没有任何意义。我确信这些用户名是 IdentityServer4 示例内存用户使用的两个默认用户,这绝非巧合,但您可以在上面看到我不再使用内存用户。事实上,即使我将GetUsers方法注释掉,这仍然是正确的Config.cs

我无法解释这一点,但无论如何我想要的是能够使用我的用户存储。因此,我进一步阅读并看到了我只能IResourceOwnerPasswordValidator与拥有GrantTypes.ResourceOwnerPassword. 但是,当我在 IS4 中更改我的 Javascript 应用程序的客户端以使用此授权类型时,当我尝试登录时,我看到了未经授权的客户端错误。

所以我被困住了。我曾认为,既然我的设置与内存用户一起工作,那么使用真正的用户存储不会有太多工作,但显然我缺少一些东西。您的指导将不胜感激。

4

1 回答 1

1

您不需要将您的ProfileService作为依赖项注入到您的服务中。

你需要类似的东西:

services.AddIdentityServer()
            .AddProfileService<CustomProfileService>()
            //..... more code

而且 - 您CustomProfileService不需要实现IProfileService(该方法接受泛型)。

真正的“魔法”发生在AccountControllerin :

/// <summary>
    /// Handle postback from username/password login
    /// </summary>
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Login(LoginInputModel model)
    {
        // logic
    }

在那里,LoginInputModel您有需要验证的用户名、密码等,所以最后IProfileService如果您正在编写自定义用户管理,则没有真正的需要。

于 2018-02-20T16:36:28.303 回答