首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Aps .net IdentityServer4授权

Aps .net IdentityServer4授权
EN

Stack Overflow用户
提问于 2017-05-11 10:50:02
回答 1查看 914关注 0票数 0

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

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

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

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

每次需要授权他执行某些操作(特别是修改/删除某些数据等操作)时,我都想询问身份服务器有关用户角色的信息。

怎么问?或者我要找什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-05-12 07:41:00

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

  • 调用OIDC UserInfo端点以获取每个请求的更新用户声明
  • 降低cookie生存期以更频繁地自动刷新用户信息
  • 在IdentityServer上实现一个自定义端点,以便它将配置文件更改信息发布到订阅客户端列表(如webapp)。
  • 当用户配置文件数据被更改时,IdentityServer强制单点签出

就实现难度而言,降低cookie生存期是最简单的(只更改cookie过期),但它不能保证最新的声明,而且对用户来说是可见的(频繁重定向到IdentityServer,但如果访问令牌生存期仍然有效,则不需要登录)。

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

端点/订阅服务器模型的性能开销最低。只有当用户配置文件信息实际更改时,才会发生UserInfo对IdentityServer的请求。这一点要执行起来要复杂一些:

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

码样本

在每次调用时从端点获取更新的UserInfo

代码语言:javascript
复制
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接收到的端点上的userIds。我没有webapp接收端点或服务的示例。

代码语言:javascript
复制
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://learn.microsoft.com/en-us/aspnet/core/security/authentication/cookie#reacting-to-back-end-changes

希望这能有所帮助!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43913286

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档