Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net core 如何从ISecurityTokenValidator正确获取依赖作用域的服务_Asp.net Core - Fatal编程技术网

Asp.net core 如何从ISecurityTokenValidator正确获取依赖作用域的服务

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

在我的asp.net core 2.0 web应用程序中,我有一个自定义的
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);
    }
}