Puis-je éviter d'utiliser BuildServiceProvider dans la fonction ExpireToken ci-dessous ? En d'autres termes...

Existe-t-il un moyen d'éviter BuildServiceProvider() dans Startup.cs lors de l'utilisation de l'événement JWTBearer OnAuthenticationFailed ?

(En utilisant l'API Web aspnet Core 3.0)

Startup.cs

public void ConfigureServices(IServiceCollection services)
    {                        
        //some code removed..

        //Authentication
        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        }).AddJwtBearer(options =>
        {
            options.Events = new JwtBearerEvents()
            {                    
                OnAuthenticationFailed = context =>
                {

                    if (context.Exception.Message.Contains("The token is expired"))
                    {
                        Microsoft.Extensions.Primitives.StringValues token = string.Empty;

                        var logger = new LoggerManager();
                        logger.LogError("Token expired"); //confirming that the token expired so authentication failed

                        var header = context.Request.Headers;

                        if (!header.TryGetValue("Authorization", out token))
                            logger.LogError("no token found");
                        else
                            token = token.ToString().Substring("Bearer ".Length).Trim();

                        ExpireToken(services, token);
                    }
                    return Task.CompletedTask;
                }
            };
         });
     }

public void ExpireToken(IServiceCollection services, string tokenId)
    {
        var sp = services.BuildServiceProvider();

        var jwtManager = sp.GetService<IJWTAuthenticationManager>();
        jwtManager.ExpireToken(tokenId);
    }

JwtAuthentication Manager publiera cet événement afin que les abonnés soient avertis (c#:event + délégués)

public delegate void TokenExpiredEventHandler(object source, TokenExpiredEventArgs args);

JWTAuthenticationManager.cs

public class JWTAuthenticationManager : IJWTAuthenticationManager
{
    private readonly string _tokenKey;      
    public event TokenExpiredEventHandler TokenExpired;

    //some code removed for brevity
    public void ExpireToken(string tokenId)
    {
        OnTokenExpired(tokenId); //notify all subscribers
    }
    protected virtual void OnTokenExpired(string token) {
        TokenExpired?.Invoke(this, new TokenExpiredEventArgs(token));
    }
}

public class TokenExpiredEventArgs : EventArgs
{
    public string token;

    public TokenExpiredEventArgs(string tokenId)
    {
        token = tokenId;
    }
}

Program.cs

public static void Main(string[] args)
    {
        var host = CreateWebHostBuilder(args).Build();

        var jwtMgr = host.Services.GetRequiredService<IJWTAuthenticationManager>();
        var cacheMgr = host.Services.GetRequiredService<ICacheManager>();
        jwtMgr.TokenExpired += cacheMgr.OnTokenExpired;

        host.Run();
    }
0
Samra 20 févr. 2020 à 08:01

1 réponse

Meilleure réponse

Pourquoi ne pas résoudre les services de context ? Changez simplement votre méthode ExpireToken pour prendre un IServiceProvider :

public void ExpireToken(IServiceProvider services, string tokenId)
{
    var jwtManager = services.GetService<IJWTAuthenticationManager>();
    jwtManager.ExpireToken(tokenId);
}

Et puis passez context.HttpContext.RequestServices :

ExpireToken(context.HttpContext.RequestServices, token);
2
Llama 20 févr. 2020 à 05:06