diff --git a/QYZH.InteractiveMagazine.Infrastructure/Auth/JwtHelper.cs b/QYZH.InteractiveMagazine.Infrastructure/Auth/JwtHelper.cs index f1f7310..9cc7b28 100644 --- a/QYZH.InteractiveMagazine.Infrastructure/Auth/JwtHelper.cs +++ b/QYZH.InteractiveMagazine.Infrastructure/Auth/JwtHelper.cs @@ -119,7 +119,7 @@ public static class JwtHelper var tokenHandler = new JwtSecurityTokenHandler(); if (tokenHandler.ReadToken(token) is JwtSecurityToken jwtToken) { - var userIdClaim = jwtToken.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier); + var userIdClaim = GetClaim(jwtToken, ClaimTypes.NameIdentifier, JwtRegisteredClaimNames.NameId, JwtRegisteredClaimNames.Sub); if (long.TryParse(userIdClaim?.Value, out long userId)) { return userId; @@ -157,8 +157,13 @@ public static class JwtHelper var tokenHandler = new JwtSecurityTokenHandler(); if (tokenHandler.ReadToken(token) is JwtSecurityToken jwtToken) { - return jwtToken.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Name)?.Value ?? string.Empty; + return GetClaim(jwtToken, ClaimTypes.Name, JwtRegisteredClaimNames.UniqueName, JwtRegisteredClaimNames.Name)?.Value ?? string.Empty; } return string.Empty; } + + private static Claim? GetClaim(JwtSecurityToken jwtToken, params string[] claimTypes) + { + return jwtToken.Claims.FirstOrDefault(c => claimTypes.Contains(c.Type)); + } } diff --git a/QYZH.InteractiveMagazine.Infrastructure/Extensions/DependencyInjectionExtensions.cs b/QYZH.InteractiveMagazine.Infrastructure/Extensions/DependencyInjectionExtensions.cs index ebfc4e7..c0e8c3b 100644 --- a/QYZH.InteractiveMagazine.Infrastructure/Extensions/DependencyInjectionExtensions.cs +++ b/QYZH.InteractiveMagazine.Infrastructure/Extensions/DependencyInjectionExtensions.cs @@ -21,6 +21,9 @@ namespace QYZH.InteractiveMagazine.Infrastructure.Extensions; /// public static class DependencyInjectionExtensions { + private const string NoAuthScheme = "NoAuth"; + private const string DevelopmentAuthScheme = "DevelopmentSmartAuth"; + /// /// Registers infrastructure services. /// @@ -34,70 +37,90 @@ public static class DependencyInjectionExtensions private static void AddJwtAuthentication(IServiceCollection services, IConfiguration configuration, IWebHostEnvironment? environment = null) { + var jwtSettings = configuration.GetSection("JwtSettings").Get()!; + services.AddSingleton(jwtSettings); + if (environment?.IsDevelopment() == true) { - services.AddAuthentication("NoAuth") - .AddScheme("NoAuth", options => { }); + services.AddAuthentication(options => + { + options.DefaultScheme = DevelopmentAuthScheme; + options.DefaultChallengeScheme = DevelopmentAuthScheme; + }) + .AddPolicyScheme(DevelopmentAuthScheme, null, options => + { + options.ForwardDefaultSelector = context => + { + var authHeader = context.Request.Headers.Authorization.FirstOrDefault(); + return !string.IsNullOrWhiteSpace(authHeader) && + authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase) + ? JwtBearerDefaults.AuthenticationScheme + : NoAuthScheme; + }; + }) + .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => ConfigureJwtBearer(options, jwtSettings)) + .AddScheme(NoAuthScheme, options => { }); return; } - var jwtSettings = configuration.GetSection("JwtSettings").Get()!; - - services.AddSingleton(jwtSettings); - services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) - .AddJwtBearer(options => + .AddJwtBearer(options => ConfigureJwtBearer(options, jwtSettings)); + } + + private static void ConfigureJwtBearer(JwtBearerOptions options, JwtSettings jwtSettings) + { + options.TokenValidationParameters = new TokenValidationParameters + { + ValidateIssuer = true, + ValidIssuer = jwtSettings.Issuer, + ValidateAudience = true, + ValidAudience = jwtSettings.Audience, + ValidateIssuerSigningKey = true, + IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.SecretKey!)), + ValidateLifetime = true, + ClockSkew = TimeSpan.Zero + }; + + options.Events = new JwtBearerEvents + { + OnTokenValidated = async context => { - options.TokenValidationParameters = new TokenValidationParameters + var currentToken = GetBearerToken(context); + if (string.IsNullOrEmpty(currentToken)) { - ValidateIssuer = true, - ValidIssuer = jwtSettings.Issuer, - ValidateAudience = true, - ValidAudience = jwtSettings.Audience, - ValidateIssuerSigningKey = true, - IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.SecretKey!)), - ValidateLifetime = true, - ClockSkew = TimeSpan.Zero - }; + context.Fail("Invalid token"); + return; + } - options.Events = new JwtBearerEvents + var userId = context.Principal?.FindFirst(ClaimTypes.NameIdentifier)?.Value; + if (string.IsNullOrEmpty(userId)) { - OnTokenValidated = async context => + context.Fail("Invalid token"); + return; + } + + var wxUserId = context.Principal?.FindFirst(JwtHelper.WxUserIdClaimType)?.Value; + if (string.IsNullOrEmpty(wxUserId)) + { + var adminToken = await RedisHelper.GetAsync(JwtHelper.BuildAdminTokenKey(userId)); + if (adminToken == currentToken) { - var currentToken = GetBearerToken(context); - if (string.IsNullOrEmpty(currentToken)) - { - context.Fail("Invalid token"); - return; - } - - var userId = context.Principal?.FindFirst(ClaimTypes.NameIdentifier)?.Value; - if (string.IsNullOrEmpty(userId)) - { - context.Fail("Invalid token"); - return; - } - - var adminToken = await RedisHelper.GetAsync(JwtHelper.BuildAdminTokenKey(userId)); - var wxUserId = context.Principal?.FindFirst(JwtHelper.WxUserIdClaimType)?.Value; - if (string.IsNullOrEmpty(wxUserId) && !string.IsNullOrEmpty(adminToken)) - { - return; - } - - if (!string.IsNullOrEmpty(wxUserId)) - { - var wechatToken = await RedisHelper.GetAsync(JwtHelper.BuildWeChatTokenKey(wxUserId, userId)); - if (wechatToken == currentToken) - { - return; - } - } - - context.Fail("Token expired, please login again"); + return; } - }; - }); + + context.Fail("Token expired, please login again"); + return; + } + + var wechatToken = await RedisHelper.GetAsync(JwtHelper.BuildWeChatTokenKey(wxUserId, userId)); + if (wechatToken == currentToken) + { + return; + } + + context.Fail("Token expired, please login again"); + } + }; } private static string? GetBearerToken(TokenValidatedContext context)