c# - 在 asp.net 中使用 JWT 实现 [Authorize(Roles = "something")]
问题描述
我是 JWT 和一般授权的新手。在我们的 .NET 4.7.2 Web 应用程序中,我们有一个 ApplicationPrincipal.cs,它有一个带有两个参数的构造函数:IPrincipal 对象和 UserAccount 对象。我们将在 JWT 令牌验证的 SetPrincipalAsync 方法中使用它。到目前为止,我们一直在 JWT 有效负载中传递一个 useId,以便从中创建一个 UserAccount 对象。但是,现在我们有一个 api 控制器,我们正在使用带有角色的 Authorize 属性(假设是在 JWT 有效负载中编码的“randomName”),并且我们不要求 JWT 有效负载中的用户 ID。我可以在我的 ApplicationPrincipal 类中有第二个构造函数,仅在我授权没有 userId 的请求的情况下接受 IPrincipal 对象,但随后 Identity 将为空。
我能够成功验证 JWT 令牌并返回一个 claimPrincipal 对象;但是,当我使用 Postman 测试我的 api 时,它返回 401 - 未授权。
public class ApplicationIdentity : IIdentity
{
public ApplicationIdentity(UserAccount account)
{
Name = account.FullName;
Account = account;
}
public UserAccount Account { get; }
public string AuthenticationType => "JWT";
public bool IsAuthenticated => true;
public string Name { get; }
}
public class ApplicationPrincipal : IPrincipal
{
private readonly IPrincipal _principal;
public IIdentity Identity { get; }
public ApplicationPrincipal(IPrincipal principal, UserAccount account)
{
_principal = principal;
Identity = new ApplicationIdentity(account);
}
public ApplicationPrincipal(IPrincipal principal)
{
_principal = principal;
}
public bool IsInRole(string role) => _principal.IsInRole(role);
}
public class TokenValidationHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken
)
{
try
{
var (principal, jwtSecurityToken) = await ValidateJwtAsync(token).ConfigureAwait(true);
var payload = ValidatePayload(jwtSecurityToken);
await SetPrincipalAsync(principal, payload).ConfigureAwait(true);
return await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
}
catch (SecurityTokenValidationException ex)
{
return request.CreateApiErrorResponse(HttpStatusCode.Unauthorized, ex);
}
catch (Exception ex)
{
return request.CreateApiErrorResponse(HttpStatusCode.InternalServerError, ex);
}
}
private static async Task SetPrincipalAsync(IPrincipal principal, JWTPayload payload)
{
if (!Guid.TryParse(payload.UserId, out var userId) && payload.api?.version != "someName")
{
throw new SecurityTokenValidationException("Token does not have valid user ID.");
}
if (payload.api?.version == "someName")
{
var myPrincipal = new ApplicationPrincipal(principal);
HttpContext.Current.User = myPrincipal;
}
else
{
var myPrincipal = new ApplicationPrincipal(principal);
var handler = new Account(userId, comeOtherValue);
var account = await CacheManager.Instance.GetOrAddAsync(handler).ConfigureAwait(true);
if (account == null)
{
throw new SecurityTokenValidationException("Could not find user account.");
}
myPrincipal = new ApplicationPrincipal(principal, account);
HttpContext.Current.User = myPrincipal;
}
}
private static async Task<(IPrincipal Principal, JwtSecurityToken Token)> ValidateJwtAsync(string token, string requestingApi)
{
// the rest of the code
ClaimsPrincipal claimsPrincipal;
SecurityToken securityToken;
var handler = new JwtSecurityTokenHandler();
try
{
claimsPrincipal = handler.ValidateToken(
token,
validationParameters,
out securityToken
);
if (requestingApi.Contains("the specific api with Role"))
{
var ci = new ClaimsIdentity();
ci.AddClaim(new Claim(ClaimTypes.Role, "roleName")); //role name applied on the api
claimsPrincipal.AddIdentity(ci);
}
}
catch (ArgumentException ex)
{
// some code
}
var jwtToken = (JwtSecurityToken)securityToken;
if (jwtToken == null)
{
//some code
}
return (claimsPrincipal, jwtToken);
}
}
[Authorize(Roles = "randomName")]
我的目标是基于具有特定嵌套属性的 JWT 有效负载
应用于控制器:{"http://clients": {"api" : {"version1" : "randomName"}}
任何意见,将不胜感激!
解决方案
推荐阅读
- mysql - “on 子句”错误中的未知列“e2.evaluationID”
- python - Python中的堆叠图像和绘图
- excel - VBA:沿列修剪多个值
- c++ - macOS Catalina 10.15 xcode openGL 没有运行窗口?
- c++ - 在我的 Windows 上下载 g++ 编译器时出错
- android - 从 PC 查找文件时,Android 不会在“下载”文件夹中显示文件
- angular - 如何在 Firebase 连接中添加 Sweet Alert?
- java - Springbatch 从两个 DB 表中读取数据并写入 XML 文件
- delphi - 如何检查表单是否在 Delphi 中关闭?
- python - Python:增加日期字符串的日期