从ClaimsPrincipal中检索/读取声明值

10
如果直接进入主题,我已经建立了一个带有基本身份验证的RESTful服务(WebAPI V2)......所有功能都按预期工作,但是我非常不确定如何从ClaimsPrincipal中检索值。我已经阅读了很多文章,但所有文章都指向使用第三方库和/或.Net中的Identity。
简而言之,我有一个执行必要逻辑的Attribute和一个自定义的authenticateService,该服务指向我的数据存储。
我有一个n层架构:
1. API 2. Service 3. Business 4. Data
所以我想第一个问题是,我怎样才能从ClaimsPrincipal中读取值?(第一次使用Claims,请见谅)
请注意:我希望这将在每个请求上触发,没有会话。
以下是一些创建和验证用户的逻辑(位于Attribute内部)
using (var authService = new AuthenticateService())
            {
                var client = await _authenticateService.AuthenticateAsync(
                    apiKey,
                    password);

                if (client != null)
                {
                    // Create a ClaimsIdentity with all the claims for this user.
                    Claim apiKeyClaim = new Claim("API Key", apiKey);
                    Claim clientNameClaim = new Claim(ClaimTypes.Name, client.ClientName);
                    Claim clientKeyClaim = new Claim("Client Key", client.ClientKey);

                    List<Claim> claims = new List<Claim>
                    {
                        apiKeyClaim,
                        clientNameClaim,
                        clientKeyClaim
                    };

                    // important to set the identity this way, otherwise IsAuthenticated will be false
                    // see: http://leastprivilege.com/2012/09/24/claimsidentity-isauthenticated-and-authenticationtype-in-net-4-5/
                    ClaimsIdentity identity = new ClaimsIdentity(claims, "Basic");
                    // AuthenticationTypes.Basic

                    var principal = new ClaimsPrincipal(identity);
                    return principal;

                    //var principal = new GenericPrincipal(new GenericIdentity("CustomIdentification"),
                    //                   new[] { "SystemUser" });

                    //return principal;
                }
                else
                {
                    return null;
                }
            }

在我的API控制器中访问声明值:

[IdentityBasicAuthentication]
    [Authorize]
    [RoutePrefix("api")]
    public class OrderController : ApiController
    {
        private IOrderService _orderService;
        public OrderController(IOrderService orderService)
        {
            _orderService = orderService;
        }
        // POST api/<controller>
        [HttpPost]
        [Route("order")]
        public async Task<IHttpActionResult> Post([FromBody]Models.Model.Order order)
        {

            var modelResponse = new ModelResponse<Models.Model.Order>(order);
            if (order == null)
                return BadRequest("Unusable resource.");

            if (!modelResponse.IsModelValid())
                return this.PropertiesRequired(modelResponse.ModelErrors());

            try
            {
                //Create abstracted Identity model to pass around layers
                // Access Claim values here
                //OR can I use Claims in other layers without creating an abstracted model to pass through.
                await _orderService.AddAsync(order);
            }
            catch (System.Exception ex)
            {
                return InternalServerError();
            }
            finally
            {
                _orderService.Dispose();
            }

            return Ok("Order Successfully Processed.");
        }
    }

非常感谢您抽出时间阅读此文,希望有“高人”能够指导/帮助我阅读声明值并且找到最佳传递层的方法。
谢谢,
5个回答

14

您可以通过以下方式访问索赔。在控制器方法中:

try 
{
    // ...
    var claimsIdentity = (ClaimsIdentity)this.RequestContext.Principal.Identity;
    foreach(var claim in claimsIdentity.Claims)
    {
        // claim.value;
        // claim.Type
    }
    // ...
}

公平地说,我使用了非常类似的东西。我想在数小时之后,我的大脑有点死了,但我还添加了一个自定义对象来传递我的类库,而不需要添加对声明和身份的依赖。 - Tez Wingfield

10
@User.Claims.FirstOrDefault(c => c.Type == "Currency").Value

3
有时口头解释是很有帮助的。 - con
完美!正是我想要的。 - Caverman
为什么没有 bool TryGetClaim(string type, out var claim) - BozoJoe
@BozoJoe 请查看 https://dev59.com/JZ_ha4cB1Zd3GeqP05Aq#75551612 - Ilias.P

1

对于那些想知道如何从 .net7 aspcore 中的 ClaimsPrincipal 获取主题 ID 的人,可以像这样轻松地完成

var claim = principal.FindFirst(Claims.Subject); 

var id = Guid.Parse(claim?.Value ?? ""); // or cast/parse it to the expected type

0

0

在 Azure Functions v3 (netcore3.1) 中查看所有权限和声明非常有用。这个功能是从各种 Stack Overflow 文章中拼凑而来的。

...
using System.Security.Claims;
using System.Linq;
...
[FunctionName("AdminOnly")]
public static async Task<IActionResult> RunAdminOnly(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = "test")] HttpRequest req,
ILogger log,
ClaimsPrincipal claimsID)
{
    string perms ="";
    foreach(var h in req.Headers)
    {
        perms += $"{h.Key}:{String.Join(",", h.Value)}" + "\n";
    }

    string claims = "";
    foreach (Claim claim in claimsID.Claims)
    {
        claims += $"{claim.Type} : {claim.Value} \n";
    }

    string claimDetail = "";
    Claim? appRole = claimsID.Claims.FirstOrDefault(c => c.Type == "extension_AppRole"); // custom claim

    claimDetail += appRole?.Value.ToString();

    return new OkObjectResult(perms + "\n\n" + claims + "\n\n" + claimDetail);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接