【问题标题】:Aps .net IdentityServer4 authorizeAps .net IdentityServer4 授权
【发布时间】:2017-10-10 07:56:06
【问题描述】:

我使用带有 asp .net 身份的 IdentityServer4 作为身份验证点。我的 API/WebApps 调用身份服务器来获取访问令牌。

现在,如何在我的 api/app 控制器中的某些操作或内部操作之前授权使用?

我可以添加角色来访问令牌,然后在控制器中(在 web api/web 应用程序中)使用 AuthorizeAttribute 并检查用户是否为 IsInRole。

但这意味着如果我要更改用户角色,他会在注销登录后看到它(因为角色是访问令牌的一部分)或令牌必须过期。

每次我需要授权身份服务器执行某些操作(尤其是修改/删除某些数据等操作)时,我都想向身份服务器询问用户角色。

问题如何? 或者我要寻找什么?

【问题讨论】:

    标签: asp.net claims-based-identity identityserver4 authorize-attribute asp.net-roles


    【解决方案1】:

    所以这里有几个可能的解决方案:

    • 调用 OIDC UserInfo Endpoint 以获取每个请求的更新用户声明
    • 降低 cookie 生命周期以更频繁地自动刷新用户信息
    • 在 IdentityServer 上实现一个自定义端点,以便将配置文件更改信息发布到订阅的客户端列表(例如您的 web 应用程序)。
    • 在更改用户配置文件数据时让 IdentityServer 强制单点注销

    就实现难度而言,降低 cookie 生命周期是最简单的(只是更改 cookie 过期时间),但它不能保证声明是最新的,并且对用户可见(经常重定向到 IdentityServer,虽然如果访问令牌生命周期仍然有效,则无需登录)

    让 webapp 在每个请求上调用 UserInfo 端点是第二简单的(参见下面的示例),但对性能的影响最差。每个请求都会产生到 IdentityServer 的往返。

    端点/订阅者模型的性能开销最低。仅当用户配置文件信息实际更改时才会发生对 IdentityServer 的 UserInfo 请求。这实现起来会有点复杂:

    1. 在您的 IdentityServer 项目中,您需要修改对配置文件数据的更改,并将 http 消息发布到您的 web 应用程序。该消息可以简单地包含修改后用户的用户 ID。此消息需要以某种方式进行身份验证,以防止恶意用户使合法用户会话无效。您可以为此包含一个 ClientCredentials 不记名令牌。
    2. 您的 web 应用程序需要接收和验证消息。它需要将更改后的用户 ID 存储在 OnValidatePrincipal 委托可访问的位置(很可能通过 DI 容器中的服务)
    3. Cookie OnValidatePrincipal 委托将注入此本地服务,以在验证主体之前检查用户信息是否已更改

    代码示例

    在每次调用时从端点获取更新的用户信息

    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        AuthenticationScheme = "NameOfYourCookieAuthSchemeHere",
        Events = new CookieAuthenticationEvents()
        {
            OnValidatePrincipal = async context =>
            {
                // Get updated UserInfo from IdentityServer
                var accessToken = context.Principal.Claims.FirstOrDefault(c => c.Type == "access_token").Value;
                var userInfoClient = new UserInfoClient("https://{IdentityServerUrlGoesHere}");
                var userInfoResponse = await userInfoClient.GetAsync(accessToken);
    
                // Invalidate Principal if Error Response
                if (userInfoResponse.IsError)
                {
                    context.RejectPrincipal();
                    await context.HttpContext.Authentication.SignOutAsync("NameOfYourCookieAuthSchemeHere");
                }
                else
                {
                    // Check if claims changed
                    var claimsChanged = userInfoResponse.Claims.Except(context.Principal.Claims).Any();
                    if (claimsChanged)
                    {
                        // Update claims and replace principal
                        var newIdentity = context.Principal.Identity as ClaimsIdentity;
                        newIdentity.AddClaims(userInfoResponse.Claims);
                        var updatedPrincipal = new ClaimsPrincipal();
                        context.ReplacePrincipal(updatedPrincipal);
                        context.ShouldRenew = true;
                    }
                }
            }
        }
    });
    

    更新来自 IdentityServer 的订阅更改消息。此示例假设您创建了一个服务(例如 IUserChangedService),该服务存储在端点从 IdentityServer 接收到的用户 ID。我没有 webapp 的接收端点或服务的示例。

    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        AuthenticationScheme = "NameOfYourCookieAuthSchemeHere",
        Events = new CookieAuthenticationEvents()
        {
            OnValidatePrincipal = async context =>
            {
                // Get User ID
                var userId = context.Principal.Claims.FirstOrDefault(c => c.Type == "UserIdClaimTypeHere");
    
                var userChangedService = context.HttpContext.RequestServices.GetRequiredService<IUserChangedService>();
                var userChanged = await userChangedService.HasUserChanged(userId);
    
                if (userChanged)
                {
                    // Make call to UserInfoEndpoint and update ClaimsPrincipal here. See example above for details
                }
            }
        }
    });
    

    除了使用本地数据库外,asp.net 核心文档也有一个示例。连接到 OnValidatePrincipal 方法的方法是相同的: https://docs.microsoft.com/en-us/aspnet/core/security/authentication/cookie#reacting-to-back-end-changes

    希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 2020-11-29
      • 2021-02-01
      • 2017-02-04
      • 2020-10-28
      • 2021-09-26
      • 2017-07-05
      • 2017-04-12
      • 2017-04-05
      • 2018-09-29
      相关资源
      最近更新 更多