Asp.net core 如何从ISecurityTokenValidator正确获取依赖作用域的服务
在我的asp.net core 2.0 web应用程序中,我有一个自定义的Asp.net core 如何从ISecurityTokenValidator正确获取依赖作用域的服务,asp.net-core,Asp.net Core,在我的asp.net core 2.0 web应用程序中,我有一个自定义的ISecurityTokenValidator,用于验证令牌 数据库查找取决于存储库-存储库本身被设置为作用域依赖项: services.AddScoped<IMyRepository>(MyRepository); 这就是它的样子: public class MyTokenValidator : ISecurityTokenValidator { private readonly IServiceP
ISecurityTokenValidator
,用于验证令牌
数据库查找取决于存储库-存储库本身被设置为作用域依赖项:
services.AddScoped<IMyRepository>(MyRepository);
这就是它的样子:
public class MyTokenValidator : ISecurityTokenValidator
{
private readonly IServiceProvider _serviceProvider;
public MyTokenValidator(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public bool CanReadToken(string securityToken) => true;
public ClaimsPrincipal ValidateToken(string securityToken, TokenValidationParameters validationParameters,
out SecurityToken validatedToken)
{
var serviceScopeFactory = _serviceProvider.GetRequiredService<IServiceScopeFactory>();
using (var scope = serviceScopeFactory.CreateScope())
{
var myRepository = scope.ServiceProvider.GetService<IMyRepository>();
var principalFactory = scope.ServiceProvider.GetService<IUserClaimsPrincipalFactory<User>>();
// Use the repo....
}
}
}
公共类MyTokenValidator:ISecurityTokenValidator
{
私有只读服务器ViceProvider\u服务提供商;
公共MyTokenValidator(IServiceProvider服务提供商)
{
_服务提供者=服务提供者;
}
public bool CanReadToken(string securityToken)=>true;
public ClaimsPrincipal ValidateToken(字符串securityToken、TokenValidationParameters、validationParameters、,
out SecurityToken validatedToken(已验证完毕)
{
var serviceScopeFactory=\u serviceProvider.GetRequiredService();
使用(var scope=serviceScopeFactory.CreateScope())
{
var myRepository=scope.ServiceProvider.GetService();
var principalFactory=scope.ServiceProvider.GetService();
//使用回购。。。。
}
}
}
现在,由于IsecurityTokenProvider
只实例化一次,因此它实际上是一个单例。当我使用服务提供商请求一个IMyRepository
时,我发现我总是收到同一个对象——就它而言,没有新的作用域,因为它在一个单例类中
为了解决这个问题,您将在上面的代码中看到,每次调用令牌验证器时,我都必须手动强制一个新的作用域。这真的是解决这一问题的唯一方法吗,我似乎正在尝试让它在这里工作…老问题,但我发现解决这个问题的最好方法是使用
IPostConfigureOptions
配置SecurityTokenValidator
首先注册JWT持有人和期权
services.AddAuthentication(options =>
{
...
}).AddJwtBearer(AuthenticateScheme, options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
...
};
});
然后注册IPostConfigureOptions
CustomJWTBeareOptionsPostConfigureOptions可能类似于:
public class CustomJwtBearerOptionsPostConfigureOptions : IPostConfigureOptions<JwtBearerOptions>
{
private readonly MyCustomSecurityTokenValidator _tokenValidator; //example dependancy
public CustomJwtBearerOptionsPostConfigureOptions(MyCustomSecurityTokenValidator tokenValidator)
{
_tokenValidator = tokenValidator;
}
public void PostConfigure(string name, JwtBearerOptions options)
{
options.SecurityTokenValidators.Clear();
options.SecurityTokenValidators.Add(_tokenValidator);
}
}
public类customjwtbeareroptions后配置选项:IPostConfigureOptions
{
私有只读MyCustomSecurityTokenValidator _tokenValidator;//示例依赖性
公共CustomJWTBeareOptionsPostConfigureOptions(MyCustomSecurityTokenValidator tokenValidator)
{
_令牌验证器=令牌验证器;
}
public void PostConfigure(字符串名称、JwtBearerOptions选项)
{
options.SecurityTokenValidators.Clear();
options.SecurityTokenValidators.Add(\u tokenValidator);
}
}
现在,options.SecurityTokenValidators由
customjwtbearerooptions postconfigureoptions
配置,它通过依赖项注入进行实例化,并可以传递相关的数据中心 我遇到了完全相同的问题,试图在令牌验证器中检索UserManager
。我最终重构了所有这些-我不需要挂断jwt Auth,所以我创建了我自己的“API密钥”Auth Middleware您不需要挂断jwt Auth是什么意思?在我的例子中,我试图从客户端授权使用GoogleOAuth发行的JWT令牌。因此,我似乎需要连接我自己的Google JWT token validator类,该类继承自ISecurityTokenValidator
,并实现ValidateToken
,然后我可以将所有令牌验证委托给google提供的类中的一个方法:google.api.Auth.GoogleJsonWebSignature.ValidateAsync
我使用的是.AddJwtToken
,但我使用的是我自己的ISecurityTokenValidator,它实际上不需要对JWT令牌做任何事情。所以我把它全部撕下来,用我自己的AuthenticationHandler
(这个问题不适用于您的场景)啊,我明白了。我在这里解释了我的需求和方法,如果你有兴趣的话:这是我迄今为止找到的唯一解决这个问题的方法,而且很好。希望它在这样的环境中有更多的可见性。谢谢。在尝试了一大堆不同的死胡同后,这是唯一一个没有脱离“死胡同”习惯而真正有效的方法。已确认在.net5.0Nice中工作。这是正确的解决方案。我从来不知道IPostConfigureOptions
!非常好:)
services.AddSingleton<IPostConfigureOptions<JwtBearerOptions>, CustomJwtBearerOptionsPostConfigureOptions>();
services.AddSingleton<MyCustomSecurityTokenValidator>();
public class CustomJwtBearerOptionsPostConfigureOptions : IPostConfigureOptions<JwtBearerOptions>
{
private readonly MyCustomSecurityTokenValidator _tokenValidator; //example dependancy
public CustomJwtBearerOptionsPostConfigureOptions(MyCustomSecurityTokenValidator tokenValidator)
{
_tokenValidator = tokenValidator;
}
public void PostConfigure(string name, JwtBearerOptions options)
{
options.SecurityTokenValidators.Clear();
options.SecurityTokenValidators.Add(_tokenValidator);
}
}