【发布时间】: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;
}
我能够在验证令牌后立即检索声明:
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。