关于c#:IdentityServer4 – API的用户权限

IdentityServer4 - user permissions on the API

我目前正在建立一个带有Web API和MVC UI的新项目(最终将拥有一个可以与同一API通信的移动UI)。

所以,我有以下计划:

  • 用户导航到MVC UI,将其带到IdentityServer4服务器以登录或注册
  • 然后将IdentityServer用户添加到数据库中的应用程序自己的用户表
  • 然后可以在用户上设置权限以限制其访问权限
  • 这意味着身份服务器只是一个身份服务器(这意味着我允许人们通过谷歌等登录,而不必担心他们的角色和权限)。

    所以,要实现上述目标,我需要检查用户对API的权限,而不是客户端(客户端可以是任何东西 - 网络,手机应用程序,JavaScript客户端等等,所以我们不能依赖它来处理用户权限)。

    在API上,我实现了Permissionhandler和PermissionRequirement授权策略。因此,在API控制器或方法上,我可以执行以下操作:[Authorize(Policy ="CreateUser")]。看起来我需要根据系统权限制定策略。

    所以在授权处理程序中我需要:

  • 获取当前用户的用户名
  • 如果它们存在于应用程序数据库中,请检查其权限并进行身份验证或拒绝
  • 如果它们不存在于应用程序数据库中,请添加它们,然后我们可以稍后从管理面板设置其权限
  • 在我尝试从身份服务器请求用户的用户名之前,情况一直很顺利。我知道我需要使用UserInfoClient来做到这一点,但我无法弄清楚如何使用用户的令牌/凭证从身份服务器获取他们的声明或至少获取他们的User.Identity.Name。

    现在我可以使用子ID将用户添加到应用程序数据库,但是无论谁管理权限都不知道该人是谁,所以我需要真正使用他们的电子邮件。

    现在在MVC客户端中,我可以看到User.Identity.Name没有任何问题,但在API中该值为null!?

    所以我的问题是:我如何从API中获取当前用户的Identity.Name,用户名或电子邮件?

    谢谢。


    我想我现在已经破解了它。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
                var mvcContext = context.Resource as Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext;
            if (mvcContext != null)
            {
                // Use the UserInfo endpoint to get the user's claims
                var discoveryClient = new DiscoveryClient("http://localhost:5000");
                var doc = await discoveryClient.GetAsync();

                var accessToken = await mvcContext.HttpContext.Authentication.GetTokenAsync("access_token");

                var userInfoClient = new UserInfoClient(doc.UserInfoEndpoint);
                var response = await userInfoClient.GetAsync(accessToken);

                var claims = response.Claims;
            }

    这在https://docs.microsoft.com/en-us/aspnet/core/security/authorization/policies的底部详细说明,因此根据Microsoft的说法,这是正确的方法。

    然而你确实激发了这个想法,谢谢Win。 几个小时我一直盯着这个血腥的东西。 你有时需要的只是别人说些什么,什么,诅咒都破了!:)

    如果有人的话,我仍然愿意接受更好的方法。

    干杯


    我相信您已经在Web API中配置IdentityServerAuthentication,类似于此 -

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
       ...
       app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
       {
          Authority ="http://UrlOfIentityServer",
          RequireHttpsMetadata = false,
          ApiName ="exampleapi"
       });
       ...
    }

    当您进行Web服务调用时,您需要传递从IdentityServer收到的相同令牌,如下所示 -

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    using (var httpClient = new HttpClient())
    {
       string accessToken = await HttpContext.Authentication.GetTokenAsync("access_token");

       httpClient.BaseAddress = new Uri("http://UrlOfWebAPI");
       httpClient.DefaultRequestHeaders.Clear();
       httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

       return await httpClient.GetStringAsync("api/clock/time");
    }