diff --git a/aspnet-core/LINGYUN.MicroService.IdentityServer.sln b/aspnet-core/LINGYUN.MicroService.IdentityServer.sln index b790ae4c6..f08a9b5cf 100644 --- a/aspnet-core/LINGYUN.MicroService.IdentityServer.sln +++ b/aspnet-core/LINGYUN.MicroService.IdentityServer.sln @@ -47,11 +47,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Entity EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdentityServer.EntityFrameworkCore", "modules\identityServer\LINGYUN.Abp.IdentityServer.EntityFrameworkCore\LINGYUN.Abp.IdentityServer.EntityFrameworkCore.csproj", "{644FAB8F-ED83-4539-AF43-8F8FE61EF778}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.WeChat.MiniProgram", "modules\wechat\LINGYUN.Abp.WeChat.MiniProgram\LINGYUN.Abp.WeChat.MiniProgram.csproj", "{648D7B5D-8B78-4F90-BDE0-4AC50C902CC3}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat.MiniProgram", "modules\wechat\LINGYUN.Abp.WeChat.MiniProgram\LINGYUN.Abp.WeChat.MiniProgram.csproj", "{648D7B5D-8B78-4F90-BDE0-4AC50C902CC3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.WeChat.Official", "modules\wechat\LINGYUN.Abp.WeChat.Official\LINGYUN.Abp.WeChat.Official.csproj", "{F762D1BB-66FB-421A-A917-D80B7DCC0DC0}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat.Official", "modules\wechat\LINGYUN.Abp.WeChat.Official\LINGYUN.Abp.WeChat.Official.csproj", "{F762D1BB-66FB-421A-A917-D80B7DCC0DC0}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.IdentityServer.WeChat", "modules\identityServer\LINGYUN.Abp.IdentityServer.WeChat\LINGYUN.Abp.IdentityServer.WeChat.csproj", "{D63C0CA8-554D-43F2-8DB4-8B464E4C1CDA}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdentityServer.WeChat", "modules\identityServer\LINGYUN.Abp.IdentityServer.WeChat\LINGYUN.Abp.IdentityServer.WeChat.csproj", "{D63C0CA8-554D-43F2-8DB4-8B464E4C1CDA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdentityServer.Domain", "modules\identityServer\LINGYUN.Abp.IdentityServer.Domain\LINGYUN.Abp.IdentityServer.Domain.csproj", "{79CAF2CA-E9E1-48A5-A21F-3786383C12E0}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -127,6 +129,10 @@ Global {D63C0CA8-554D-43F2-8DB4-8B464E4C1CDA}.Debug|Any CPU.Build.0 = Debug|Any CPU {D63C0CA8-554D-43F2-8DB4-8B464E4C1CDA}.Release|Any CPU.ActiveCfg = Release|Any CPU {D63C0CA8-554D-43F2-8DB4-8B464E4C1CDA}.Release|Any CPU.Build.0 = Release|Any CPU + {79CAF2CA-E9E1-48A5-A21F-3786383C12E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {79CAF2CA-E9E1-48A5-A21F-3786383C12E0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {79CAF2CA-E9E1-48A5-A21F-3786383C12E0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {79CAF2CA-E9E1-48A5-A21F-3786383C12E0}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -155,6 +161,7 @@ Global {648D7B5D-8B78-4F90-BDE0-4AC50C902CC3} = {AF8AECC8-0F42-4FC5-B3C0-00987BA8279F} {F762D1BB-66FB-421A-A917-D80B7DCC0DC0} = {AF8AECC8-0F42-4FC5-B3C0-00987BA8279F} {D63C0CA8-554D-43F2-8DB4-8B464E4C1CDA} = {98887A8F-7040-4FA1-842F-A4C77A61ED09} + {79CAF2CA-E9E1-48A5-A21F-3786383C12E0} = {98887A8F-7040-4FA1-842F-A4C77A61ED09} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {FCB77471-9ECB-4666-A316-1D6A6285A468} diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/SmsValidator/SmsTokenGrantValidator.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/SmsValidator/SmsTokenGrantValidator.cs index ce9fdc292..81465bcdb 100644 --- a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/SmsValidator/SmsTokenGrantValidator.cs +++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/SmsValidator/SmsTokenGrantValidator.cs @@ -15,6 +15,7 @@ using System.Threading.Tasks; using Volo.Abp.IdentityServer.Localization; using Volo.Abp.Security.Claims; using IdentityUser = Volo.Abp.Identity.IdentityUser; +using IdentityResource = Volo.Abp.Identity.Localization.IdentityResource; namespace LINGYUN.Abp.IdentityServer.SmsValidator { diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/MiniProgram/WeChatMiniProgramGrantValidator.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/MiniProgram/WeChatMiniProgramGrantValidator.cs index d3588e02e..221483b96 100644 --- a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/MiniProgram/WeChatMiniProgramGrantValidator.cs +++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/MiniProgram/WeChatMiniProgramGrantValidator.cs @@ -1,24 +1,12 @@ -using IdentityModel; -using IdentityServer4.Events; -using IdentityServer4.Models; -using IdentityServer4.Services; -using IdentityServer4.Validation; -using LINGYUN.Abp.WeChat; +using IdentityServer4.Services; using LINGYUN.Abp.WeChat.MiniProgram; using LINGYUN.Abp.WeChat.OpenId; -using LINGYUN.Abp.WeChat.Security.Claims; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Localization; -using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using System; -using System.Collections.Generic; -using System.Net.Http; -using System.Security.Claims; using System.Threading.Tasks; using Volo.Abp.Identity; using Volo.Abp.IdentityServer.Localization; -using Volo.Abp.Security.Claims; using IdentityUser = Volo.Abp.Identity.IdentityUser; namespace LINGYUN.Abp.IdentityServer.WeChat.MiniProgram @@ -26,93 +14,32 @@ namespace LINGYUN.Abp.IdentityServer.WeChat.MiniProgram /// /// 对于小程序绑定用户的扩展授权验证器 /// - public class WeChatMiniProgramGrantValidator : IExtensionGrantValidator + public class WeChatMiniProgramGrantValidator : WeChatGrantValidator { - protected ILogger Logger { get; } - protected AbpWeChatMiniProgramOptions Options { get; } - protected IHttpClientFactory HttpClientFactory{ get; } - protected IEventService EventService { get; } - protected IWeChatOpenIdFinder WeChatOpenIdFinder { get; } - protected IIdentityUserRepository UserRepository { get; } - protected UserManager UserManager { get; } - protected SignInManager SignInManager { get; } - protected IStringLocalizer Localizer { get; } - protected PhoneNumberTokenProvider PhoneNumberTokenProvider { get; } + public override string GrantType => AbpWeChatMiniProgramConsts.GrantType; + + public override string LoginProviderKey => AbpWeChatMiniProgramConsts.ProviderKey; + public override string AuthenticationMethod => AbpWeChatMiniProgramConsts.AuthenticationMethod; + + protected AbpWeChatMiniProgramOptions Options { get; } public WeChatMiniProgramGrantValidator( IEventService eventService, IWeChatOpenIdFinder weChatOpenIdFinder, - IHttpClientFactory httpClientFactory, UserManager userManager, IIdentityUserRepository userRepository, - SignInManager signInManager, - IStringLocalizer stringLocalizer, - PhoneNumberTokenProvider phoneNumberTokenProvider, - IOptions options, - ILogger logger) + IStringLocalizer identityLocalizer, + IStringLocalizer identityServerLocalizer, + IOptions options) + : base(eventService, weChatOpenIdFinder, userManager, userRepository, identityLocalizer, identityServerLocalizer) { - Logger = logger; Options = options.Value; - - EventService = eventService; - UserManager = userManager; - SignInManager = signInManager; - Localizer = stringLocalizer; - UserRepository = userRepository; - WeChatOpenIdFinder = weChatOpenIdFinder; - HttpClientFactory = httpClientFactory; - PhoneNumberTokenProvider = phoneNumberTokenProvider; } - public string GrantType => AbpWeChatMiniProgramConsts.GrantType; - - public async Task ValidateAsync(ExtensionGrantValidationContext context) + protected override async Task FindOpenIdAsync(string code) { - var raw = context.Request.Raw; - var credential = raw.Get(OidcConstants.TokenRequest.GrantType); - if (credential == null || !credential.Equals(GrantType)) - { - Logger.LogWarning("Invalid grant type: not allowed"); - context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, - Localizer["InvalidGrant:GrantTypeInvalid"]); - return; - } - // TODO: 统一命名规范, 微信认证传递的 code 改为 WeChatOpenIdConsts.WeCahtCodeKey - var wechatCode = raw.Get(AbpWeChatGlobalConsts.TokenName); - if (wechatCode.IsNullOrWhiteSpace() || wechatCode.IsNullOrWhiteSpace()) - { - Logger.LogWarning("Invalid grant type: wechat code not found"); - context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, - Localizer["InvalidGrant:WeChatCodeNotFound"]); - return; - } - var wechatOpenId = await WeChatOpenIdFinder.FindAsync(wechatCode, Options.AppId, Options.AppSecret); - // 如果存在 UnionId优先使用 - var currentUser = await UserManager.FindByLoginAsync(AbpWeChatMiniProgramConsts.ProviderKey, wechatOpenId.UnionId ?? wechatOpenId.OpenId); - if(currentUser == null) - { - Logger.LogWarning("Invalid grant type: wechat openid: {0} not register", wechatOpenId.OpenId); - context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, - Localizer["InvalidGrant:WeChatNotRegister"]); - return; - } - var sub = await UserManager.GetUserIdAsync(currentUser); - - var additionalClaims = new List(); - if (currentUser.TenantId.HasValue) - { - additionalClaims.Add(new Claim(AbpClaimTypes.TenantId, currentUser.TenantId?.ToString())); - } - additionalClaims.Add(new Claim(AbpWeChatClaimTypes.OpenId, wechatOpenId.OpenId)); - if (!wechatOpenId.UnionId.IsNullOrWhiteSpace()) - { - additionalClaims.Add(new Claim(AbpWeChatClaimTypes.UnionId, wechatOpenId.UnionId)); - } - - await EventService.RaiseAsync(new UserLoginSuccessEvent(currentUser.UserName, wechatOpenId.OpenId, null)); - context.Result = new GrantValidationResult(sub, - AbpWeChatMiniProgramConsts.AuthenticationMethod, additionalClaims.ToArray()); + return await WeChatOpenIdFinder.FindAsync(code, Options.AppId, Options.AppSecret); } } } diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/Official/WeChatOfficialGrantValidator.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/Official/WeChatOfficialGrantValidator.cs index 0de5acf5a..548b8b8d1 100644 --- a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/Official/WeChatOfficialGrantValidator.cs +++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/Official/WeChatOfficialGrantValidator.cs @@ -1,24 +1,12 @@ -using IdentityModel; -using IdentityServer4.Events; -using IdentityServer4.Models; -using IdentityServer4.Services; -using IdentityServer4.Validation; -using LINGYUN.Abp.WeChat; +using IdentityServer4.Services; using LINGYUN.Abp.WeChat.Official; using LINGYUN.Abp.WeChat.OpenId; -using LINGYUN.Abp.WeChat.Security.Claims; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Localization; -using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using System; -using System.Collections.Generic; -using System.Net.Http; -using System.Security.Claims; using System.Threading.Tasks; using Volo.Abp.Identity; using Volo.Abp.IdentityServer.Localization; -using Volo.Abp.Security.Claims; using IdentityUser = Volo.Abp.Identity.IdentityUser; namespace LINGYUN.Abp.IdentityServer.WeChat.Official @@ -26,92 +14,32 @@ namespace LINGYUN.Abp.IdentityServer.WeChat.Official /// /// 对于公众平台绑定用户的扩展授权验证器 /// - public class WeChatOfficialGrantValidator : IExtensionGrantValidator + public class WeChatOfficialGrantValidator : WeChatGrantValidator { - protected ILogger Logger { get; } - protected AbpWeChatOfficialOptions Options { get; } - protected IHttpClientFactory HttpClientFactory { get; } - protected IEventService EventService { get; } - protected IWeChatOpenIdFinder WeChatOpenIdFinder { get; } - protected IIdentityUserRepository UserRepository { get; } - protected UserManager UserManager { get; } - protected SignInManager SignInManager { get; } - protected IStringLocalizer Localizer { get; } - protected PhoneNumberTokenProvider PhoneNumberTokenProvider { get; } + public override string GrantType => AbpWeChatOfficialConsts.GrantType; + + public override string LoginProviderKey => AbpWeChatOfficialConsts.ProviderKey; + public override string AuthenticationMethod => AbpWeChatOfficialConsts.AuthenticationMethod; + + protected AbpWeChatOfficialOptions Options { get; } public WeChatOfficialGrantValidator( - IEventService eventService, - IWeChatOpenIdFinder weChatOpenIdFinder, - IHttpClientFactory httpClientFactory, - UserManager userManager, + IEventService eventService, + IWeChatOpenIdFinder weChatOpenIdFinder, + UserManager userManager, IIdentityUserRepository userRepository, - SignInManager signInManager, - IStringLocalizer stringLocalizer, - PhoneNumberTokenProvider phoneNumberTokenProvider, - IOptions options, - ILogger logger) + IStringLocalizer identityLocalizer, + IStringLocalizer identityServerLocalizer, + IOptions options) + : base(eventService, weChatOpenIdFinder, userManager, userRepository, identityLocalizer, identityServerLocalizer) { - Logger = logger; Options = options.Value; - - EventService = eventService; - UserManager = userManager; - SignInManager = signInManager; - Localizer = stringLocalizer; - UserRepository = userRepository; - WeChatOpenIdFinder = weChatOpenIdFinder; - HttpClientFactory = httpClientFactory; - PhoneNumberTokenProvider = phoneNumberTokenProvider; } - public string GrantType => AbpWeChatOfficialConsts.GrantType; - - public async Task ValidateAsync(ExtensionGrantValidationContext context) + protected override async Task FindOpenIdAsync(string code) { - var raw = context.Request.Raw; - var credential = raw.Get(OidcConstants.TokenRequest.GrantType); - if (credential == null || !credential.Equals(GrantType)) - { - Logger.LogWarning("Invalid grant type: not allowed"); - context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, - Localizer["InvalidGrant:GrantTypeInvalid"]); - return; - } - // TODO: 统一命名规范, 微信认证传递的 code 改为 WeChatOpenIdConsts.WeCahtCodeKey - var wechatCode = raw.Get(AbpWeChatGlobalConsts.TokenName); - if (wechatCode.IsNullOrWhiteSpace() || wechatCode.IsNullOrWhiteSpace()) - { - Logger.LogWarning("Invalid grant type: wechat code not found"); - context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, - Localizer["InvalidGrant:WeChatCodeNotFound"]); - return; - } - var wechatOpenId = await WeChatOpenIdFinder.FindAsync(wechatCode, Options.AppId, Options.AppSecret); - var currentUser = await UserManager.FindByLoginAsync(AbpWeChatOfficialConsts.ProviderKey, wechatOpenId.OpenId); - if (currentUser == null) - { - Logger.LogWarning("Invalid grant type: wechat openid: {0} not register", wechatOpenId.OpenId); - context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, - Localizer["InvalidGrant:WeChatNotRegister"]); - return; - } - var sub = await UserManager.GetUserIdAsync(currentUser); - - var additionalClaims = new List(); - if (currentUser.TenantId.HasValue) - { - additionalClaims.Add(new Claim(AbpClaimTypes.TenantId, currentUser.TenantId?.ToString())); - } - additionalClaims.Add(new Claim(AbpWeChatClaimTypes.OpenId, wechatOpenId.OpenId)); - if (!wechatOpenId.UnionId.IsNullOrWhiteSpace()) - { - additionalClaims.Add(new Claim(AbpWeChatClaimTypes.UnionId, wechatOpenId.UnionId)); - } - - await EventService.RaiseAsync(new UserLoginSuccessEvent(currentUser.UserName, wechatOpenId.OpenId, null)); - context.Result = new GrantValidationResult(sub, - AbpWeChatOfficialConsts.AuthenticationMethod, additionalClaims.ToArray()); + return await WeChatOpenIdFinder.FindAsync(code, Options.AppId, Options.AppSecret); } } } diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/WeChatGrantValidator.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/WeChatGrantValidator.cs new file mode 100644 index 000000000..f0b14daae --- /dev/null +++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/WeChatGrantValidator.cs @@ -0,0 +1,116 @@ + +using IdentityModel; +using IdentityServer4.Events; +using IdentityServer4.Models; +using IdentityServer4.Services; +using IdentityServer4.Validation; +using LINGYUN.Abp.WeChat; +using LINGYUN.Abp.WeChat.OpenId; +using LINGYUN.Abp.WeChat.Security.Claims; +using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using System; +using System.Collections.Generic; +using System.Security.Claims; +using System.Threading.Tasks; +using Volo.Abp.Identity; +using Volo.Abp.IdentityServer.Localization; +using Volo.Abp.Security.Claims; +using IdentityResource = Volo.Abp.Identity.Localization.IdentityResource; +using IdentityUser = Volo.Abp.Identity.IdentityUser; + +namespace LINGYUN.Abp.IdentityServer.WeChat +{ + public abstract class WeChatGrantValidator : IExtensionGrantValidator + { + public abstract string GrantType { get; } + public abstract string LoginProviderKey { get; } + public abstract string AuthenticationMethod { get; } + + public ILogger Logger { protected get; set; } + protected IEventService EventService { get; } + protected IWeChatOpenIdFinder WeChatOpenIdFinder { get; } + protected IIdentityUserRepository UserRepository { get; } + protected UserManager UserManager { get; } + protected IStringLocalizer IdentityLocalizer { get; } + protected IStringLocalizer IdentityServerLocalizer { get; } + + public WeChatGrantValidator( + IEventService eventService, + IWeChatOpenIdFinder weChatOpenIdFinder, + UserManager userManager, + IIdentityUserRepository userRepository, + IStringLocalizer identityLocalizer, + IStringLocalizer identityServerLocalizer) + { + EventService = eventService; + UserManager = userManager; + UserRepository = userRepository; + WeChatOpenIdFinder = weChatOpenIdFinder; + IdentityLocalizer = identityLocalizer; + IdentityServerLocalizer = identityServerLocalizer; + + Logger = NullLogger.Instance; + } + + protected abstract Task FindOpenIdAsync(string code); + + public async Task ValidateAsync(ExtensionGrantValidationContext context) + { + var raw = context.Request.Raw; + var credential = raw.Get(OidcConstants.TokenRequest.GrantType); + if (credential == null || !credential.Equals(GrantType)) + { + Logger.LogWarning("Invalid grant type: not allowed"); + context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, IdentityServerLocalizer["InvalidGrant:GrantTypeInvalid"]); + return; + } + // TODO: 统一命名规范, 微信认证传递的 code 改为 WeChatOpenIdConsts.WeCahtCodeKey + var wechatCode = raw.Get(AbpWeChatGlobalConsts.TokenName); + if (wechatCode.IsNullOrWhiteSpace() || wechatCode.IsNullOrWhiteSpace()) + { + Logger.LogWarning("Invalid grant type: wechat code not found"); + context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, IdentityServerLocalizer["InvalidGrant:WeChatCodeNotFound"]); + return; + } + + var wechatOpenId = await FindOpenIdAsync(wechatCode); + var currentUser = await UserManager.FindByLoginAsync(LoginProviderKey, wechatOpenId.OpenId); + if (currentUser == null) + { + Logger.LogWarning("Invalid grant type: wechat openid not register", wechatOpenId.OpenId); + context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, IdentityServerLocalizer["InvalidGrant:WeChatNotRegister"]); + return; + } + + if (await UserManager.IsLockedOutAsync(currentUser)) + { + Logger.LogInformation("Authentication failed for username: {username}, reason: locked out", currentUser.UserName); + context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, IdentityLocalizer["Volo.Abp.Identity:UserLockedOut"]); + return; + } + + var sub = await UserManager.GetUserIdAsync(currentUser); + + var additionalClaims = new List(); + if (currentUser.TenantId.HasValue) + { + additionalClaims.Add(new Claim(AbpClaimTypes.TenantId, currentUser.TenantId?.ToString())); + } + additionalClaims.Add(new Claim(AbpWeChatClaimTypes.OpenId, wechatOpenId.OpenId)); + if (!wechatOpenId.UnionId.IsNullOrWhiteSpace()) + { + additionalClaims.Add(new Claim(AbpWeChatClaimTypes.UnionId, wechatOpenId.UnionId)); + } + + await EventService.RaiseAsync(new UserLoginSuccessEvent(currentUser.UserName, wechatOpenId.OpenId, null)); + + context.Result = new GrantValidationResult(sub, AuthenticationMethod, additionalClaims.ToArray()); + + // 登录之后需要更新安全令牌 + (await UserManager.UpdateSecurityStampAsync(currentUser)).CheckErrors(); + } + } +} diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/Microsoft/AspNetCore/Authentication/WeChat/Official/WeChatOfficialOAuthHandler.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/Microsoft/AspNetCore/Authentication/WeChat/Official/WeChatOfficialOAuthHandler.cs index de391d059..ffbc716f2 100644 --- a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/Microsoft/AspNetCore/Authentication/WeChat/Official/WeChatOfficialOAuthHandler.cs +++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/Microsoft/AspNetCore/Authentication/WeChat/Official/WeChatOfficialOAuthHandler.cs @@ -88,7 +88,7 @@ namespace Microsoft.AspNetCore.Authentication.WeChat.Official // TODO: 此处通过唯一的 CorrelationId, 将 properties生成的State缓存删除 var state = Request.Query["state"]; - var stateCacheKey = WeChatOfficialStateCacheItem.CalculateCacheKey(state, null); + var stateCacheKey = WeChatOfficialStateCacheItem.CalculateCacheKey(state.ToString().ToMd5(), null); await Cache.RemoveAsync(stateCacheKey, token: Context.RequestAborted); return new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name); @@ -138,10 +138,12 @@ namespace Microsoft.AspNetCore.Authentication.WeChat.Official await base.HandleChallengeAsync(properties); // TODO: 此处已经生成唯一的 CorrelationId, 可以借此将 properties生成State之后再进行缓存 + // 注: 默认的State对于微信来说太长(微信只支持128位长度的State),因此巧妙的利用CorrelationId的MD5值来替代State + // MD5转换防止直接通过CorrelationId干些别的事情... var state = properties.Items[".xsrf"]; var stateToken = Options.StateDataFormat.Protect(properties); - var stateCacheKey = WeChatOfficialStateCacheItem.CalculateCacheKey(state, null); + var stateCacheKey = WeChatOfficialStateCacheItem.CalculateCacheKey(state.ToMd5(), null); await Cache .SetAsync( @@ -177,7 +179,7 @@ namespace Microsoft.AspNetCore.Authentication.WeChat.Official ["response_type"] = "code" }); - challengeUrl += $"&scope={scope}&state={state}"; + challengeUrl += $"&scope={scope}&state={state.ToMd5()}"; return challengeUrl; } @@ -189,7 +191,7 @@ namespace Microsoft.AspNetCore.Authentication.WeChat.Official // TODO: 此处借用唯一的 CorrelationId, 将 properties生成的State缓存取出,进行解密 var state = query["state"]; - var stateCacheKey = WeChatOfficialStateCacheItem.CalculateCacheKey(state, null); + var stateCacheKey = WeChatOfficialStateCacheItem.CalculateCacheKey(state.ToString().ToMd5(), null); var stateCacheItem = await Cache.GetAsync(stateCacheKey, token: Context.RequestAborted); var properties = Options.StateDataFormat.Unprotect(stateCacheItem.State); diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/Microsoft/AspNetCore/Authentication/WeChat/Official/WeChatOfficialOAuthOptions.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/Microsoft/AspNetCore/Authentication/WeChat/Official/WeChatOfficialOAuthOptions.cs index ce812c8bd..8ff9f9e11 100644 --- a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/Microsoft/AspNetCore/Authentication/WeChat/Official/WeChatOfficialOAuthOptions.cs +++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/Microsoft/AspNetCore/Authentication/WeChat/Official/WeChatOfficialOAuthOptions.cs @@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.Authentication.WeChat.Official { public WeChatOfficialOAuthOptions() { - // 用于防止初始化错误 + // 用于防止初始化错误,会在OAuthHandler.InitializeHandlerAsync中进行重写 ClientId = "WeChatOfficial"; ClientSecret = "WeChatOfficial"; diff --git a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.MiniProgram/LINGYUN/Abp/WeChat/MiniProgram/AbpWeChatMiniProgramConsts.cs b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.MiniProgram/LINGYUN/Abp/WeChat/MiniProgram/AbpWeChatMiniProgramConsts.cs index bed3fd9cb..32cd7d6da 100644 --- a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.MiniProgram/LINGYUN/Abp/WeChat/MiniProgram/AbpWeChatMiniProgramConsts.cs +++ b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.MiniProgram/LINGYUN/Abp/WeChat/MiniProgram/AbpWeChatMiniProgramConsts.cs @@ -3,7 +3,7 @@ public class AbpWeChatMiniProgramConsts { /// - /// 全局对应的Provider名称 + /// 微信小程序对应的Provider名称 /// public static string ProviderKey { get; set; } = "WeChat.MiniProgram"; diff --git a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/AbpWeChatOfficialConsts.cs b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/AbpWeChatOfficialConsts.cs index 03d52d33e..d57bf895e 100644 --- a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/AbpWeChatOfficialConsts.cs +++ b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/AbpWeChatOfficialConsts.cs @@ -3,7 +3,7 @@ public class AbpWeChatOfficialConsts { /// - /// 微信公众号全局对应的Provider名称 + /// 微信公众号对应的Provider名称 /// public static string ProviderKey { get; set; } = "WeChat.Official"; diff --git a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/AbpWeChatGlobalConsts.cs b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/AbpWeChatGlobalConsts.cs index 3ba456eb3..dc7e7bce2 100644 --- a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/AbpWeChatGlobalConsts.cs +++ b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/AbpWeChatGlobalConsts.cs @@ -14,5 +14,7 @@ /// 微信授权显示名称 /// public static string DisplayName { get; set; } = "WeChat"; + + public static string HttpClient { get; set; } = "Abp.WeChat"; } } diff --git a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/AbpWeChatModule.cs b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/AbpWeChatModule.cs index bdcc28207..5a5805d4b 100644 --- a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/AbpWeChatModule.cs +++ b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/AbpWeChatModule.cs @@ -31,11 +31,12 @@ namespace LINGYUN.Abp.WeChat .AddVirtualJson("/LINGYUN/Abp/WeChat/Localization/Resources"); }); - context.Services.AddHttpClient("WeChatRequestClient", options => - { - options.BaseAddress = new Uri("https://api.weixin.qq.com"); - }).AddTransientHttpErrorPolicy(builder => - builder.WaitAndRetryAsync(3, i => TimeSpan.FromSeconds(Math.Pow(2, i)))); + context.Services.AddHttpClient(AbpWeChatGlobalConsts.HttpClient, + options => + { + options.BaseAddress = new Uri("https://api.weixin.qq.com"); + }).AddTransientHttpErrorPolicy(builder => + builder.WaitAndRetryAsync(3, i => TimeSpan.FromSeconds(Math.Pow(2, i)))); } } } diff --git a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/OpenId/WeChatOpenIdFinder.cs b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/OpenId/WeChatOpenIdFinder.cs index 634a030a3..f0d9c68cd 100644 --- a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/OpenId/WeChatOpenIdFinder.cs +++ b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/OpenId/WeChatOpenIdFinder.cs @@ -58,7 +58,7 @@ namespace LINGYUN.Abp.WeChat.OpenId Logger.LogDebug($"Not found in the cache, getting from the httpClient: {cacheKey}"); - var client = HttpClientFactory.CreateClient("WeChatRequestClient"); + var client = HttpClientFactory.CreateClient(AbpWeChatGlobalConsts.HttpClient); var request = new WeChatOpenIdRequest { diff --git a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/Token/WeChatTokenProvider.cs b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/Token/WeChatTokenProvider.cs index 066b96159..8c8d8fbec 100644 --- a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/Token/WeChatTokenProvider.cs +++ b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/Token/WeChatTokenProvider.cs @@ -58,7 +58,7 @@ namespace LINGYUN.Abp.WeChat.Token Logger.LogDebug($"Not found in the cache, getting from the httpClient: {cacheKey}"); - var client = HttpClientFactory.CreateClient("WeChatRequestClient"); + var client = HttpClientFactory.CreateClient(AbpWeChatGlobalConsts.HttpClient); var request = new WeChatTokenRequest {