【问题标题】:Get Claims in a WebApi Control from a JWT Token从 JWT 令牌获取 WebApi 控件中的声明
【发布时间】:2022-01-19 09:48:47
【问题描述】:

这是我第一次尝试使用 Asp.Net Core Web Api。我有一切工作,包括身份验证和 jwt 令牌创建和验证。我要做的是提取令牌中的用户信息,并在将数据发布到数据库时使用其中的一些信息。我这样创建令牌:

    public string NewToken(string ApiKey, ICAN_Context context)
    {
        var user = context.TblUserLogins.Where(x => x.ApiKey == ApiKey).FirstOrDefault();
        int? CompanyId = context.TblEmployeeCompanies.Where(x => x.EmployeeId == user.EmployeeId).Select(x => x.CompanyId).FirstOrDefault();
        var identity = new ClaimsIdentity();
        identity.AddClaim(new Claim(ClaimTypes.Name, user.UserName));
        identity.AddClaim(new Claim("CompanyId", CompanyId.ToString(), ClaimValueTypes.Integer32));
        identity.AddClaim(new Claim("EmployeeCompanyId", user.EmployeeCompanyId.ToString(), ClaimValueTypes.Integer32 ));
        var tokenDescriptor = new SecurityTokenDescriptor
        {
            Subject = new ClaimsIdentity(identity),
            Expires = DateTime.UtcNow.AddMinutes(60),
            SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(secretKey), SecurityAlgorithms.HmacSha256Signature)
        };
        var token = tokenHandler.CreateToken(tokenDescriptor);
        var jwtString = tokenHandler.WriteToken(token);
        return jwtString;

    }

我使用“过滤器”验证令牌:

    public void OnAuthorization(AuthorizationFilterContext context)
    {
        var tokenManager = (ITokenManager)context.HttpContext.RequestServices.GetService(typeof(ITokenManager));
        var result = true;
        if(!context.HttpContext.Request.Headers.ContainsKey("Authorization"))
        {
            result = false;
        }
        string token = string.Empty;
        if(result)
        {
            token = context.HttpContext.Request.Headers.First(x=>x.Key == "Authorization").Value;
            try
            {
                var claimPrinciple = tokenManager.VerifyToken(token);

            }
            catch(Exception ex)
            {
                result = false;
                context.ModelState.AddModelError("Unauthorized", ex.ToString());
            }
        }
        if(!result)
        {
            context.Result = new UnauthorizedObjectResult(context.ModelState);
        }
    }

我从令牌中检索声明信息没有问题,我的问题是如何在我的控制器方法中从令牌中获取声明?

我希望能够在我的方法中检索它的值,如下所示:

    [HttpPost]
    [Route("~/api/entity/department")]
    public IActionResult CreateDepartment([FromBody] TblCompanyDepartmentsXlu department)
    {
        var identity = (ClaimsIdentity)User.Identity;
      
        _context.Departments.Add(department);
        _context.SaveChanges();
        return Ok("Department created successfully!");
    }

我也从StackOverflow尝试过这个:

    public static ClaimsPrincipal VerifyToken(string jwtToken)
    {
        TokenManager tokenManager = new TokenManager();
        SecurityToken validatedToken;
        TokenValidationParameters validationParameters = new TokenValidationParameters();
        validationParameters.ValidateLifetime = true;
        validationParameters.IssuerSigningKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(tokenManager.secretKey);
        validationParameters.ValidateAudience = false;
        validationParameters.ValidateIssuer = false;
        ClaimsPrincipal principal = new JwtSecurityTokenHandler().ValidateToken(jwtToken, validationParameters, out validatedToken);
    
        return principal;

    }

    [HttpGet]
    [Route("~/api/entity/GetEmployees")]
    public List<TblEmployees> GetEmployees()
    {
        var identity = HttpContext.User.Identity as ClaimsIdentity;
        if (identity != null)
        {
            IEnumerable<Claim> claims = identity.Claims;


        }
        var employees = _context.Employees.ToList();
        return employees;

    }

identity.Claims 始终为 0。

我能够在验证令牌后立即检索声明:

                    var claimPrinciple = TokenManager.VerifyToken(token);

我可以在这里检索索赔信息

var claims = claimPrinciple.Identities.First().Claims.ToList();
int? CompanyId = Convert.ToInt32(claims.Where(x => x.Type == "CompanyId").FirstOrDefault().Value);
int EmployeeCompanyId = Convert.ToInt32(claims.Where(x => x.Type == "EmployeeCompanyId").FirstOrDefault().Value);

但我无法在控制器中检索它们。

【问题讨论】:

  • 如果您在 jwt.io 上查看原始令牌中的声明是什么?
  • 用户名、CompanyId 和 EmployeeCompanyId
  • 您是否在启动时配置了您的 JWT 选项? Take a look 在这篇博文中。
  • @klekmek - 不。这是我的启动中的内容:services.AddTransient(); services.AddDbContext(options => options.UseSqlServer(Configuration.GetConnectionString("ICANDatabase"))); services.AddControllers();
  • 我建议您使用内置的 JWT Bearer 身份验证方法进行身份验证。这些将与您的控制器完美集成并填充ClaimsPrincipal

标签: asp.net-core-webapi


【解决方案1】:
//startup.cs dotnet 6.0 :
builder.Services.AddHttpContextAccessor();
.
.
.
//where you want to use the IHttpContextAccessor :
//For example in user repository : 
private readonly IHttpContextAccessor _httpContextAccessor;

    public UserRepository(IHttpContextAccessor httpContextAccessor) =>
        _httpContextAccessor = httpContextAccessor;

    public void LogCurrentUser()
    {
        var username = _httpContextAccessor.HttpContext.User.Identity.Name;
        // ...
    }

【讨论】:

  • 不幸的是,我没有存储库,但此信息很有用。谢谢!
  • 我很高兴亲爱的。存储库只是一个示例,您可以使用您需要的控制器和其他类来代替存储库。
【解决方案2】:

@Klekmek 是正确的。我需要做的就是使用内置的 JWT 令牌功能(我不知道它存在)。我删除了 AuthenticationFilter 并将其添加到我的启动中: 到 ConfigureServices 部分:

services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        })
        .AddJwtBearer(jwt => {
            var key = Encoding.ASCII.GetBytes(Configuration["JwtConfig:Secret"]);
            jwt.SaveToken = true;
            jwt.TokenValidationParameters = new TokenValidationParameters()
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(key),
                ValidateLifetime = true,
                ValidateIssuer = false,
                ValidateAudience = false
            };
        });

还有配置部分:

app.UseAuthentication();

添加之后,这行得通:

 var identity = HttpContext.User.Identity as ClaimsIdentity;

【讨论】:

    猜你喜欢
    • 2018-06-16
    • 2021-04-21
    • 2017-02-13
    • 2019-04-17
    • 2020-01-17
    • 2023-03-23
    • 2019-06-17
    • 2017-09-28
    • 1970-01-01
    相关资源
    最近更新 更多