首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在IdentityServer4运行时添加/管理用户声明

如何在IdentityServer4运行时添加/管理用户声明
EN

Stack Overflow用户
提问于 2017-04-18 10:06:50
回答 1查看 2.2K关注 0票数 6

我正在尝试在一个新项目中使用IdentityServer4。我在PluralSight视频“理解ASP.NET核心安全”中看到,IdentityServer4可以与基于声明的安全性一起使用来保护web。我已经将我的IdentityServer4设置为一个单独的项目/解决方案。

我还看到,您可以添加一个IProfileService来向IdentityServer4返回的令牌添加自定义声明。

一个计划是向用户添加新的声明,允许他们访问api的不同部分。但是,我不知道如何管理来自api项目的IdentityServer用户的声明。我想我应该调用IdentotyServer4来添加和删除一个用户声明?

此外,一般来说,这是一种很好的方法,因为我不确定允许客户为自己的内部安全目的向IdentityServer添加声明是有意义的--并且可能导致冲突(例如多个客户端使用“角色”声明和值“admin”)。也许我应该在api项目中本地处理安全性,然后使用“sub”声明来查找它们?

有谁有好的方法吗?

谢谢

EN

回答 1

Stack Overflow用户

发布于 2018-06-11 16:07:52

老问题,但仍然相关。正如我在评论中所说的

声明是关于身份的,而不是权限。

这听起来是对的,但标识也可能包含哪些类型的用户(Admin、User、Manager等),这些用户可以用来确定API中的权限。也许设置具有特定权限的用户角色?本质上,如果CLIENT1-Admin不应该具有与CLIENT2-Admin相同的权限,您也可以在客户端之间划分角色以进行更多的控制。

因此,将您的角色作为IProfileService中的声明传递。

代码语言:javascript
复制
public class ProfileService : IProfileService
{
    private readonly Services.IUserService _userService;

    public ProfileService(Services.IUserService userService)
    {
        _userService = userService;
    }

    public async Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        try
        {
            switch (context.Client.ClientId)
            {
                //setup profile data for each different client
                case "CLIENT1":
                {
                    //sub is your userId.
                    var userId = context.Subject.Claims.FirstOrDefault(x => x.Type == "sub");

                    if (!string.IsNullOrEmpty(userId?.Value) && long.Parse(userId.Value) > 0)
                    {
                        //get the actual user object from the database
                        var user = await _userService.GetUserAsync(long.Parse(userId.Value));

                        // issue the claims for the user
                        if (user != null)
                        {
                            var claims = GetCLIENT1Claims(user);

                            //add the claims
                            context.IssuedClaims = claims.Where(x => context.RequestedClaimTypes.Contains(x.Type)).ToList();
                        }
                    }
                }
                break;
                case "CLIENT2":
                {
                    //...
                }
            }
        }
        catch (Exception ex) 
        {
            //log your exceptions
        }
    }

    // Gets all significant user claims that should be included
    private static Claim[] GetCLIENT1Claims(User user)
    {
        var claims = new List<Claim>
        {
            new Claim("user_id", user.UserId.ToString() ?? ""),
            new Claim(JwtClaimTypes.Name, user.Name),
            new Claim(JwtClaimTypes.Email, user.Email ?? ""),
            new Claim("some_other_claim", user.Some_Other_Info ?? "")
        };

        //----- THIS IS WHERE ROLES ARE ADDED ------
        //user roles which are just string[] = { "CLIENT1-Admin", "CLIENT1-User", .. }
        foreach (string role in user.Roles)
            claims.Add(new Claim(JwtClaimTypes.Role, role));

        return claims.ToArray();
    }
}

然后为您的特定权限向控制器添加[Authorize]属性。这只允许特定角色访问它们,从而设置您自己的权限。

代码语言:javascript
复制
[Authorize(Roles = "CLIENT1-Admin, CLIENT2-Admin, ...")]
public class ValuesController : Controller
{
    //...
}

上述声明也可以在身份验证时传递,例如,如果您使用的是带有自定义ResourceOwner的ResourceOwnerPasswordValidator设置。您可以在验证方法中以相同的方式传递声明,如下所示。

代码语言:javascript
复制
context.Result = new GrantValidationResult(
    subject: user.UserId.ToString(),
    authenticationMethod: "custom",
    claims: GetClaims(user));

因此,正如最少特权所说的,您不希望使用IdentityServer设置权限并将其作为声明传递(比如谁可以编辑什么记录),因为它们过于具体,并且混淆了令牌,但是设置的角色-

允许他们访问api的不同部分。

这对于用户角色来说是非常好的。

希望这能有所帮助。

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

https://stackoverflow.com/questions/43469229

复制
相关文章

相似问题

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