Nic*_*las 7 jwt bearer-token asp.net-core
在我的API项目中,我使用JwtBearer处理身份验证(用户使用Azure登录).调用API时,使用定义的Azure实例验证令牌,这一切都正常.
成功验证令牌后,已使用适当的角色将已登录的用户插入到我们自己的数据库中.现在处理的方式如下:
// Add authentication (Azure AD)
services
.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
sharedOptions.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.Audience = this.Configuration["AzureAd:ClientId"];
options.Authority = $"{this.Configuration["AzureAd:Instance"]}{this.Configuration["AzureAd:TenantId"]}";
options.Events = new JwtBearerEvents()
{
OnTokenValidated = context =>
{
// Check if the user has an OID claim
if (!context.Principal.HasClaim(c => c.Type == "http://schemas.microsoft.com/identity/claims/objectidentifier"))
{
context.Fail($"The claim 'oid' is not present in the token.");
}
ClaimsPrincipal userPrincipal = context.Principal;
// Check is user exists, if not then insert the user in our own database
CheckUser cu = new CheckUser(
context.HttpContext.RequestServices.GetRequiredService<DBContext>(),
context.HttpContext.RequestServices.GetRequiredService<UserManager<ApplicationUser>>(),
userPrincipal);
cu.CreateUser();
return Task.CompletedTask;
},
};
});
Run Code Online (Sandbox Code Playgroud)
这工作正常,但它不是最美丽/正确的方法.我会说我应该使用依赖注入/覆盖OnTokenValidated事件并在CheckUser那里集成' '逻辑,以便startup类保持整洁.
遗憾的是我缺乏关于DI的知识,我不完全确定最好的方法是正确处理这个问题.因此,我看了一下,找到了一个确切描述我的问题的帖子:
使用在startup.cs中分配的委托处理OnTokenValidated的问题
读完这篇文章之后,我尝试用自己的逻辑对它进行一些修改,最后我得到了以下内容:
在初创公司:
services.AddScoped<UserValidation>();
services
.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
sharedOptions.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.Audience = this.Configuration["AzureAd:ClientId"];
options.Authority = $"{this.Configuration["AzureAd:Instance"]}{this.Configuration["AzureAd:TenantId"]}";
options.EventsType = typeof(UserValidation);
});
Run Code Online (Sandbox Code Playgroud)
Custom JwtBearerEvents类:
public class UserValidation : JwtBearerEvents
{
private string UserID { get; set; }
private string UserEmail { get; set; }
private string UserName { get; set; }
public override async Task TokenValidated(TokenValidatedContext context)
{
try
{
TRSContext context2 = context.HttpContext.RequestServices.GetRequiredService<TRSContext>();
UserManager<ApplicationUser> userManager = context.HttpContext.RequestServices.GetRequiredService<UserManager<ApplicationUser>>();
ClaimsPrincipal userPrincipal = context.Principal;
this.UserID = userPrincipal.Claims.First(c => c.Type == "http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
if (userPrincipal.HasClaim(c => c.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"))
{
this.UserEmail = userPrincipal.Claims.First(c => c.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress").Value;
}
if (userPrincipal.HasClaim(c => c.Type == "name"))
{
this.UserName = userPrincipal.Claims.First(c => c.Type == "name").Value;
}
var checkUser = userManager.FindByIdAsync(this.UserID).Result;
if (checkUser == null)
{
checkUser = new ApplicationUser
{
Id = this.UserID,
Email = this.UserEmail,
UserName = this.UserEmail,
};
var result = userManager.CreateAsync(checkUser).Result;
// Assign Roles
if (result.Succeeded)
{
return;
}
else
{
throw new Exception(result.Errors.First().Description);
}
}
}
catch (Exception)
{
throw;
}
}
}
Run Code Online (Sandbox Code Playgroud)
然而,由于某种原因,这不起作用.没有错误,UserValidation永远不会被命中(尝试设置调试点,但它永远不会命中),并且它不会插入新用户(在使用旧代码时会这样做).
任何人都知道我在这里做错了什么或者有一些更好的想法如何处理这个?