From fd3be86af212f199a7e19cf3c5ed853b76149a40 Mon Sep 17 00:00:00 2001
From: cKey <35512826+colinin@users.noreply.github.com>
Date: Wed, 4 Nov 2020 21:17:30 +0800
Subject: [PATCH] Added WeChat external login provider
---
aspnet-core/LINGYUN.MicroService.All.sln | 2 +-
....Abp.IdentityServer.WeChatValidator.csproj | 4 +
.../AbpIdentityServerWeChatValidatorModule.cs | 11 +
.../AspNetIdentity/AbpWeChatProfileService.cs | 5 +-
.../IWeChatResourceDataSeeder.cs | 9 +
.../WeChatResourceDataSeeder.cs | 85 +++++
.../WeChatSignatureMiddleware.cs | 6 +-
.../WeChatTokenGrantValidator.cs | 15 +-
.../Authorization/UserWeChatCodeFinder.cs | 22 +-
.../WeChat/WeChatAuthenticationHandler.cs | 316 ++++++++++++++++++
.../WeChat/WeChatAuthenticationOptions.cs | 54 +++
.../WeChatAuthenticationStateCacheItem.cs | 18 +
.../WeChatAuthenticationExtensions.cs | 64 ++++
.../System/BytesExtensions.cs | 16 +
.../System/StringExtensions.cs | 17 +
.../System/Text/Json/JsonElementExtensions.cs | 63 ++++
.../WeChatWeAppNotificationPublishProvider.cs | 16 +-
.../AbpWeChatAuthorizationConsts.cs | 72 ++++
.../AbpWeChatAuthorizationModule.cs | 2 +-
...ns.cs => AbpWeChatAuthorizationOptions.cs} | 2 +-
.../Authorization/AbpWeChatClaimTypes.cs | 48 +++
...deFinder.cs => IUserWeChatOpenIdFinder.cs} | 2 +-
.../OpenId/IWeChatOpenIdFinder.cs | 4 -
...inder.cs => NullUserWeChatOpenIdFinder.cs} | 6 +-
.../OpenId/WeChatOpenIdFinder.cs | 25 +-
.../Token/WeChatTokenProvider.cs | 4 +-
.../WeChatAuthorizationConsts.cs | 22 --
.../Abp/Security/Claims/WeChatClaimTypes.cs | 8 -
.../Volo/Abp/Users/CurrentUserExtensions.cs | 6 +-
.../AuthIdentityServerModule.cs | 9 +-
.../IdentityServerDataSeedContributor.cs | 15 +-
...eSiteCookiesServiceCollectionExtensions.cs | 10 +-
32 files changed, 843 insertions(+), 115 deletions(-)
create mode 100644 aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/IWeChatResourceDataSeeder.cs
create mode 100644 aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatResourceDataSeeder.cs
create mode 100644 aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/Microsoft/AspNetCore/Authentication/WeChat/WeChatAuthenticationHandler.cs
create mode 100644 aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/Microsoft/AspNetCore/Authentication/WeChat/WeChatAuthenticationOptions.cs
create mode 100644 aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/Microsoft/AspNetCore/Authentication/WeChat/WeChatAuthenticationStateCacheItem.cs
create mode 100644 aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/Microsoft/AspNetCore/Authentication/WeChatAuthenticationExtensions.cs
create mode 100644 aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/System/BytesExtensions.cs
create mode 100644 aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/System/StringExtensions.cs
create mode 100644 aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/System/Text/Json/JsonElementExtensions.cs
create mode 100644 aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/AbpWeChatAuthorizationConsts.cs
rename aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/{AbpWeChatOptions.cs => AbpWeChatAuthorizationOptions.cs} (76%)
create mode 100644 aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/AbpWeChatClaimTypes.cs
rename aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/OpenId/{IUserWeChatCodeFinder.cs => IUserWeChatOpenIdFinder.cs} (83%)
rename aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/OpenId/{NullUserWeChatCodeFinder.cs => NullUserWeChatOpenIdFinder.cs} (61%)
delete mode 100644 aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/WeChatAuthorizationConsts.cs
delete mode 100644 aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/Volo/Abp/Security/Claims/WeChatClaimTypes.cs
diff --git a/aspnet-core/LINGYUN.MicroService.All.sln b/aspnet-core/LINGYUN.MicroService.All.sln
index a91f6cf7c..ea419eead 100644
--- a/aspnet-core/LINGYUN.MicroService.All.sln
+++ b/aspnet-core/LINGYUN.MicroService.All.sln
@@ -259,7 +259,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AspNetCore.Sign
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "wechat", "wechat", "{DD9BE9E7-F6BF-4869-BCD2-82F5072BDA21}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.WeChat", "modules\wechat\LINGYUN.Abp.WeChat\LINGYUN.Abp.WeChat.csproj", "{BAE74ABC-1096-495F-A624-BEBFBC1896F2}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat", "modules\wechat\LINGYUN.Abp.WeChat\LINGYUN.Abp.WeChat.csproj", "{BAE74ABC-1096-495F-A624-BEBFBC1896F2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN.Abp.IdentityServer.WeChatValidator.csproj b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN.Abp.IdentityServer.WeChatValidator.csproj
index e02f2e7f2..241c181ff 100644
--- a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN.Abp.IdentityServer.WeChatValidator.csproj
+++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN.Abp.IdentityServer.WeChatValidator.csproj
@@ -25,4 +25,8 @@
+
+
+
+
diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/AbpIdentityServerWeChatValidatorModule.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/AbpIdentityServerWeChatValidatorModule.cs
index 1fb0af4e3..000356b5c 100644
--- a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/AbpIdentityServerWeChatValidatorModule.cs
+++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/AbpIdentityServerWeChatValidatorModule.cs
@@ -1,6 +1,8 @@
using LINGYUN.Abp.IdentityServer.AspNetIdentity;
using LINGYUN.Abp.IdentityServer.WeChatValidator;
using LINGYUN.Abp.WeChat.Authorization;
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.IdentityServer;
using Volo.Abp.IdentityServer.Localization;
@@ -17,6 +19,8 @@ namespace LINGYUN.Abp.IdentityServer
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
+ var configuration = context.Services.GetConfiguration();
+
PreConfigure(builder =>
{
builder.AddProfileService();
@@ -30,6 +34,13 @@ namespace LINGYUN.Abp.IdentityServer
Configure(configuration.GetSection("WeChat:Signature"));
+ context.Services
+ .AddAuthentication()
+ .AddWeChat(options => // 加入微信认证登录
+ {
+ configuration.GetSection("WeChat:Auth")?.Bind(options);
+ });
+
Configure(options =>
{
options.FileSets.AddEmbedded();
diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/AspNetIdentity/AbpWeChatProfileService.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/AspNetIdentity/AbpWeChatProfileService.cs
index 9cb7a6ca5..11246cab3 100644
--- a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/AspNetIdentity/AbpWeChatProfileService.cs
+++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/AspNetIdentity/AbpWeChatProfileService.cs
@@ -1,5 +1,6 @@
using IdentityServer4.AspNetIdentity;
using IdentityServer4.Models;
+using LINGYUN.Abp.WeChat.Authorization;
using Microsoft.AspNetCore.Identity;
using System.Linq;
using System.Security.Principal;
@@ -32,8 +33,8 @@ namespace LINGYUN.Abp.IdentityServer.AspNetIdentity
await base.GetProfileDataAsync(context);
// TODO: 可以从令牌获取openid, 安全性呢?
- TryAddWeChatClaim(context, WeChatClaimTypes.OpenId);
- TryAddWeChatClaim(context, WeChatClaimTypes.UnionId);
+ TryAddWeChatClaim(context, AbpWeChatClaimTypes.OpenId);
+ TryAddWeChatClaim(context, AbpWeChatClaimTypes.UnionId);
}
}
diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/IWeChatResourceDataSeeder.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/IWeChatResourceDataSeeder.cs
new file mode 100644
index 000000000..38d591d26
--- /dev/null
+++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/IWeChatResourceDataSeeder.cs
@@ -0,0 +1,9 @@
+using System.Threading.Tasks;
+
+namespace LINGYUN.Abp.IdentityServer
+{
+ public interface IWeChatResourceDataSeeder
+ {
+ Task CreateStandardResourcesAsync();
+ }
+}
diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatResourceDataSeeder.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatResourceDataSeeder.cs
new file mode 100644
index 000000000..eb2e69766
--- /dev/null
+++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatResourceDataSeeder.cs
@@ -0,0 +1,85 @@
+using LINGYUN.Abp.WeChat.Authorization;
+using System.Threading.Tasks;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Guids;
+using Volo.Abp.Identity;
+using Volo.Abp.IdentityServer.IdentityResources;
+
+namespace LINGYUN.Abp.IdentityServer
+{
+ public class WeChatResourceDataSeeder : IWeChatResourceDataSeeder, ITransientDependency
+ {
+ protected IIdentityClaimTypeRepository ClaimTypeRepository { get; }
+ protected IIdentityResourceRepository IdentityResourceRepository { get; }
+ protected IGuidGenerator GuidGenerator { get; }
+
+ public WeChatResourceDataSeeder(
+ IIdentityResourceRepository identityResourceRepository,
+ IGuidGenerator guidGenerator,
+ IIdentityClaimTypeRepository claimTypeRepository)
+ {
+ IdentityResourceRepository = identityResourceRepository;
+ GuidGenerator = guidGenerator;
+ ClaimTypeRepository = claimTypeRepository;
+ }
+
+ public virtual async Task CreateStandardResourcesAsync()
+ {
+ var wechatClaimTypes = new string[]
+ {
+ AbpWeChatClaimTypes.AvatarUrl,
+ AbpWeChatClaimTypes.City,
+ AbpWeChatClaimTypes.Country,
+ AbpWeChatClaimTypes.NickName,
+ AbpWeChatClaimTypes.OpenId,
+ AbpWeChatClaimTypes.Privilege,
+ AbpWeChatClaimTypes.Province,
+ AbpWeChatClaimTypes.Sex,
+ AbpWeChatClaimTypes.UnionId
+ };
+
+ var wechatResource = new IdentityServer4.Models.IdentityResource(
+ AbpWeChatAuthorizationConsts.ProfileKey,
+ AbpWeChatAuthorizationConsts.DisplayName,
+ wechatClaimTypes);
+
+ foreach (var claimType in wechatClaimTypes)
+ {
+ await AddClaimTypeIfNotExistsAsync(claimType);
+ }
+
+ await AddIdentityResourceIfNotExistsAsync(wechatResource);
+ }
+
+ protected virtual async Task AddIdentityResourceIfNotExistsAsync(IdentityServer4.Models.IdentityResource resource)
+ {
+ if (await IdentityResourceRepository.CheckNameExistAsync(resource.Name))
+ {
+ return;
+ }
+
+ await IdentityResourceRepository.InsertAsync(
+ new IdentityResource(
+ GuidGenerator.Create(),
+ resource
+ )
+ );
+ }
+
+ protected virtual async Task AddClaimTypeIfNotExistsAsync(string claimType)
+ {
+ if (await ClaimTypeRepository.AnyAsync(claimType))
+ {
+ return;
+ }
+
+ await ClaimTypeRepository.InsertAsync(
+ new IdentityClaimType(
+ GuidGenerator.Create(),
+ claimType,
+ isStatic: true
+ )
+ );
+ }
+ }
+}
diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatSignatureMiddleware.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatSignatureMiddleware.cs
index 48c3a040d..74b1a70b7 100644
--- a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatSignatureMiddleware.cs
+++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatSignatureMiddleware.cs
@@ -2,8 +2,6 @@
using Microsoft.Extensions.Options;
using System;
using System.Collections;
-using System.Security.Cryptography;
-using System.Text;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
@@ -63,9 +61,7 @@ namespace LINGYUN.Abp.IdentityServer
signatureStr += al[i];
}
// step3 SHA1加密
- using var sha1 = new SHA1CryptoServiceProvider();
- byte[] bytes_in = Encoding.ASCII.GetBytes(signatureStr);
- byte[] bytes_out = sha1.ComputeHash(bytes_in);
+ byte[] bytes_out = signatureStr.Sha1();
string result = BitConverter.ToString(bytes_out).Replace("-", "");
// step4 比对
if (result.Equals(signature, StringComparison.CurrentCultureIgnoreCase))
diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatValidator/WeChatTokenGrantValidator.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatValidator/WeChatTokenGrantValidator.cs
index 444a9fef7..25827a066 100644
--- a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatValidator/WeChatTokenGrantValidator.cs
+++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatValidator/WeChatTokenGrantValidator.cs
@@ -23,7 +23,7 @@ namespace LINGYUN.Abp.IdentityServer.WeChatValidator
public class WeChatTokenGrantValidator : IExtensionGrantValidator
{
protected ILogger Logger { get; }
- protected AbpWeChatOptions Options { get; }
+ protected AbpWeChatAuthorizationOptions Options { get; }
protected IHttpClientFactory HttpClientFactory{ get; }
protected IEventService EventService { get; }
protected IWeChatOpenIdFinder WeChatOpenIdFinder { get; }
@@ -43,7 +43,7 @@ namespace LINGYUN.Abp.IdentityServer.WeChatValidator
SignInManager signInManager,
IStringLocalizer stringLocalizer,
PhoneNumberTokenProvider phoneNumberTokenProvider,
- IOptions options,
+ IOptions options,
ILogger logger)
{
Logger = logger;
@@ -82,7 +82,7 @@ namespace LINGYUN.Abp.IdentityServer.WeChatValidator
return;
}
var wechatOpenId = await WeChatOpenIdFinder.FindAsync(wechatCode);
- var currentUser = await UserManager.FindByLoginAsync(WeChatAuthorizationConsts.ProviderKey, wechatOpenId.OpenId);
+ var currentUser = await UserManager.FindByLoginAsync(AbpWeChatAuthorizationConsts.ProviderKey, wechatOpenId.OpenId);
if(currentUser == null)
{
Logger.LogWarning("Invalid grant type: wechat openid: {0} not register", wechatOpenId.OpenId);
@@ -92,20 +92,15 @@ namespace LINGYUN.Abp.IdentityServer.WeChatValidator
}
var sub = await UserManager.GetUserIdAsync(currentUser);
- // 微信登录的用户写入token
- currentUser.SetToken(WeChatAuthorizationConsts.ProviderKey, WeChatAuthorizationConsts.WeCahtCodeKey, wechatCode);
- currentUser.SetToken(WeChatAuthorizationConsts.ProviderKey, WeChatAuthorizationConsts.WeCahtOpenIdKey, wechatOpenId.OpenId);
- currentUser.SetToken(WeChatAuthorizationConsts.ProviderKey, WeChatAuthorizationConsts.WeCahtSessionKey, wechatOpenId.SessionKey);
-
var additionalClaims = new List();
if (currentUser.TenantId.HasValue)
{
additionalClaims.Add(new Claim(AbpClaimTypes.TenantId, currentUser.TenantId?.ToString()));
}
- additionalClaims.Add(new Claim(WeChatClaimTypes.OpenId, wechatOpenId.OpenId));
+ additionalClaims.Add(new Claim(AbpWeChatClaimTypes.OpenId, wechatOpenId.OpenId));
if (!wechatOpenId.UnionId.IsNullOrWhiteSpace())
{
- additionalClaims.Add(new Claim(WeChatClaimTypes.UnionId, wechatOpenId.UnionId));
+ additionalClaims.Add(new Claim(AbpWeChatClaimTypes.UnionId, wechatOpenId.UnionId));
}
await EventService.RaiseAsync(new UserLoginSuccessEvent(currentUser.UserName, wechatOpenId.OpenId, null));
diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/WeChat/Authorization/UserWeChatCodeFinder.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/WeChat/Authorization/UserWeChatCodeFinder.cs
index e0a966910..39a384e10 100644
--- a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/WeChat/Authorization/UserWeChatCodeFinder.cs
+++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/WeChat/Authorization/UserWeChatCodeFinder.cs
@@ -1,15 +1,15 @@
using Microsoft.Extensions.DependencyInjection;
using System;
+using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Identity;
namespace LINGYUN.Abp.WeChat.Authorization
{
- // TODO: 真正的项目需要扩展Abp框架实体来关联微信
[Dependency(ServiceLifetime.Transient, ReplaceServices = true)]
- [ExposeServices(typeof(IUserWeChatCodeFinder))]
- public class UserWeChatCodeFinder : IUserWeChatCodeFinder
+ [ExposeServices(typeof(IUserWeChatOpenIdFinder))]
+ public class UserWeChatCodeFinder : IUserWeChatOpenIdFinder
{
protected IdentityUserManager UserManager { get; }
@@ -23,18 +23,24 @@ namespace LINGYUN.Abp.WeChat.Authorization
{
var user = await UserManager.FindByIdAsync(userId.ToString());
- var weChatCodeToken = user?.FindToken(WeChatAuthorizationConsts.ProviderKey, WeChatAuthorizationConsts.WeCahtCodeKey);
-
- return weChatCodeToken?.Value ?? userId.ToString();
+ return GetUserOpenIdOrNull(user);
}
public virtual async Task FindByUserNameAsync(string userName)
{
var user = await UserManager.FindByNameAsync(userName);
- var weChatCodeToken = user?.FindToken(WeChatAuthorizationConsts.ProviderKey, WeChatAuthorizationConsts.WeCahtCodeKey);
+ return GetUserOpenIdOrNull(user);
+ }
+
+ protected string GetUserOpenIdOrNull(IdentityUser user)
+ {
+ // 微信扩展登录后openid存储在Login中
+ var userLogin = user?.Logins
+ .Where(login => login.LoginProvider == AbpWeChatAuthorizationConsts.ProviderKey)
+ .FirstOrDefault();
- return weChatCodeToken?.Value ?? userName;
+ return userLogin?.ProviderKey;
}
}
}
diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/Microsoft/AspNetCore/Authentication/WeChat/WeChatAuthenticationHandler.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/Microsoft/AspNetCore/Authentication/WeChat/WeChatAuthenticationHandler.cs
new file mode 100644
index 000000000..446c9cb59
--- /dev/null
+++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/Microsoft/AspNetCore/Authentication/WeChat/WeChatAuthenticationHandler.cs
@@ -0,0 +1,316 @@
+using LINGYUN.Abp.WeChat.Authorization;
+using Microsoft.AspNetCore.Authentication.OAuth;
+using Microsoft.AspNetCore.WebUtilities;
+using Microsoft.Extensions.Caching.Distributed;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using Microsoft.Extensions.Primitives;
+using Microsoft.Net.Http.Headers;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Net.Http;
+using System.Security.Claims;
+using System.Text;
+using System.Text.Encodings.Web;
+using System.Text.Json;
+using System.Threading.Tasks;
+using Volo.Abp.Caching;
+
+namespace Microsoft.AspNetCore.Authentication.WeChat
+{
+ public class WeChatAuthenticationHandler : OAuthHandler
+ {
+ protected IDistributedCache Cache { get; }
+ public WeChatAuthenticationHandler(
+ IDistributedCache cache,
+ IOptionsMonitor options,
+ ILoggerFactory logger,
+ UrlEncoder encoder,
+ ISystemClock clock)
+ : base(options, logger, encoder, clock)
+ {
+ Cache = cache;
+ }
+
+ protected override async Task CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens)
+ {
+ var address = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, new Dictionary
+ {
+ ["access_token"] = tokens.AccessToken,
+ ["openid"] = tokens.Response.GetRootString("openid")
+ });
+
+ var response = await Backchannel.GetAsync(address);
+ if (!response.IsSuccessStatusCode)
+ {
+ Logger.LogError("An error occurred while retrieving the user profile: the remote server " +
+ "returned a {Status} response with the following payload: {Headers} {Body}.",
+ /* Status: */ response.StatusCode,
+ /* Headers: */ response.Headers.ToString(),
+ /* Body: */ await response.Content.ReadAsStringAsync());
+
+ throw new HttpRequestException("An error occurred while retrieving user information.");
+ }
+
+ var payload = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
+ if (!string.IsNullOrEmpty(payload.GetRootString("errcode")))
+ {
+ Logger.LogError("An error occurred while retrieving the user profile: the remote server " +
+ "returned a {Status} response with the following payload: {Headers} {Body}.",
+ /* Status: */ response.StatusCode,
+ /* Headers: */ response.Headers.ToString(),
+ /* Body: */ await response.Content.ReadAsStringAsync());
+
+ throw new HttpRequestException("An error occurred while retrieving user information.");
+ }
+
+ var context = new OAuthCreatingTicketContext(new ClaimsPrincipal(identity), properties, Context, Scheme, Options, Backchannel, tokens, payload.RootElement);
+ context.RunClaimActions();
+
+ await Events.CreatingTicket(context);
+
+ // TODO: 此处通过唯一的 CorrelationId, 将 properties生成的State缓存删除
+ var state = Request.Query["state"];
+
+ var stateCacheKey = WeChatAuthenticationStateCacheItem.CalculateCacheKey(state, null);
+ await Cache.RemoveAsync(stateCacheKey, token: Context.RequestAborted);
+
+ return new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name);
+ }
+
+ ///
+ /// code换取access_token
+ ///
+ protected override async Task ExchangeCodeAsync(OAuthCodeExchangeContext context)
+ {
+ var address = QueryHelpers.AddQueryString(Options.TokenEndpoint, new Dictionary()
+ {
+ ["appid"] = Options.ClientId,
+ ["secret"] = Options.ClientSecret,
+ ["code"] = context.Code,
+ ["grant_type"] = "authorization_code"
+ });
+
+ var response = await Backchannel.GetAsync(address);
+ if (!response.IsSuccessStatusCode)
+ {
+ Logger.LogError("An error occurred while retrieving an access token: the remote server " +
+ "returned a {Status} response with the following payload: {Headers} {Body}.",
+ /* Status: */ response.StatusCode,
+ /* Headers: */ response.Headers.ToString(),
+ /* Body: */ await response.Content.ReadAsStringAsync());
+
+ return OAuthTokenResponse.Failed(new Exception("An error occurred while retrieving an access token."));
+ }
+
+ var payload = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
+ if (!string.IsNullOrEmpty(payload.GetRootString("errcode")))
+ {
+ Logger.LogError("An error occurred while retrieving an access token: the remote server " +
+ "returned a {Status} response with the following payload: {Headers} {Body}.",
+ /* Status: */ response.StatusCode,
+ /* Headers: */ response.Headers.ToString(),
+ /* Body: */ await response.Content.ReadAsStringAsync());
+
+ return OAuthTokenResponse.Failed(new Exception("An error occurred while retrieving an access token."));
+ }
+ return OAuthTokenResponse.Success(payload);
+ }
+
+ protected override async Task HandleChallengeAsync(AuthenticationProperties properties)
+ {
+ await base.HandleChallengeAsync(properties);
+
+ // TODO: 此处已经生成唯一的 CorrelationId, 可以借此将 properties生成State之后再进行缓存
+ var state = properties.Items[".xsrf"];
+
+ var stateToken = Options.StateDataFormat.Protect(properties);
+ var stateCacheKey = WeChatAuthenticationStateCacheItem.CalculateCacheKey(state, null);
+
+ await Cache
+ .SetAsync(
+ stateCacheKey,
+ new WeChatAuthenticationStateCacheItem(stateToken),
+ new DistributedCacheEntryOptions
+ {
+ AbsoluteExpiration = Clock.UtcNow.AddMinutes(2) // TODO: 设定2分钟过期?
+ },
+ token: Context.RequestAborted);
+ }
+ ///
+ /// 构建用户授权地址
+ ///
+ protected override string BuildChallengeUrl(AuthenticationProperties properties, string redirectUri)
+ {
+ var state = properties.Items[".xsrf"];
+
+ var isWeChatBrewserRequest = IsWeChatBrowser();
+
+ var scope = isWeChatBrewserRequest
+ ? AbpWeChatAuthorizationConsts.UserInfoScope
+ : FormatScope();
+
+ var endPoint = isWeChatBrewserRequest
+ ? Options.AuthorizationEndpoint
+ : AbpWeChatAuthorizationConsts.QrConnectEndpoint;
+
+ var challengeUrl = QueryHelpers.AddQueryString(endPoint, new Dictionary
+ {
+ ["appid"] = Options.ClientId,
+ ["redirect_uri"] = redirectUri,
+ ["response_type"] = "code"
+ });
+
+ challengeUrl += $"&scope={scope}&state={state}";
+
+ return challengeUrl;
+ }
+
+ protected override async Task HandleRemoteAuthenticateAsync()
+ {
+ var query = Request.Query;
+
+ // TODO: 此处借用唯一的 CorrelationId, 将 properties生成的State缓存取出,进行解密
+ var state = query["state"];
+
+ var stateCacheKey = WeChatAuthenticationStateCacheItem.CalculateCacheKey(state, null);
+ var stateCacheItem = await Cache.GetAsync(stateCacheKey, token: Context.RequestAborted);
+
+ var properties = Options.StateDataFormat.Unprotect(stateCacheItem.State);
+
+ if (properties == null)
+ {
+ return HandleRequestResult.Fail("The oauth state was missing or invalid.");
+ }
+
+ // OAuth2 10.12 CSRF
+ if (!ValidateCorrelationId(properties))
+ {
+ return HandleRequestResult.Fail("Correlation failed.", properties);
+ }
+
+ var error = query["error"];
+ if (!StringValues.IsNullOrEmpty(error))
+ {
+ // Note: access_denied errors are special protocol errors indicating the user didn't
+ // approve the authorization demand requested by the remote authorization server.
+ // Since it's a frequent scenario (that is not caused by incorrect configuration),
+ // denied errors are handled differently using HandleAccessDeniedErrorAsync().
+ // Visit https://tools.ietf.org/html/rfc6749#section-4.1.2.1 for more information.
+ var errorDescription = query["error_description"];
+ var errorUri = query["error_uri"];
+ if (StringValues.Equals(error, "access_denied"))
+ {
+ var result = await HandleAccessDeniedErrorAsync(properties);
+ if (!result.None)
+ {
+ return result;
+ }
+ var deniedEx = new Exception("Access was denied by the resource owner or by the remote server.");
+ deniedEx.Data["error"] = error.ToString();
+ deniedEx.Data["error_description"] = errorDescription.ToString();
+ deniedEx.Data["error_uri"] = errorUri.ToString();
+
+ return HandleRequestResult.Fail(deniedEx, properties);
+ }
+
+ var failureMessage = new StringBuilder();
+ failureMessage.Append(error);
+ if (!StringValues.IsNullOrEmpty(errorDescription))
+ {
+ failureMessage.Append(";Description=").Append(errorDescription);
+ }
+ if (!StringValues.IsNullOrEmpty(errorUri))
+ {
+ failureMessage.Append(";Uri=").Append(errorUri);
+ }
+
+ var ex = new Exception(failureMessage.ToString());
+ ex.Data["error"] = error.ToString();
+ ex.Data["error_description"] = errorDescription.ToString();
+ ex.Data["error_uri"] = errorUri.ToString();
+
+ return HandleRequestResult.Fail(ex, properties);
+ }
+
+ var code = query["code"];
+
+ if (StringValues.IsNullOrEmpty(code))
+ {
+ return HandleRequestResult.Fail("Code was not found.", properties);
+ }
+
+ var codeExchangeContext = new OAuthCodeExchangeContext(properties, code, BuildRedirectUri(Options.CallbackPath));
+ using var tokens = await ExchangeCodeAsync(codeExchangeContext);
+
+ if (tokens.Error != null)
+ {
+ return HandleRequestResult.Fail(tokens.Error, properties);
+ }
+
+ if (string.IsNullOrEmpty(tokens.AccessToken))
+ {
+ return HandleRequestResult.Fail("Failed to retrieve access token.", properties);
+ }
+
+ var identity = new ClaimsIdentity(ClaimsIssuer);
+
+ if (Options.SaveTokens)
+ {
+ var authTokens = new List();
+
+ authTokens.Add(new AuthenticationToken { Name = "access_token", Value = tokens.AccessToken });
+ if (!string.IsNullOrEmpty(tokens.RefreshToken))
+ {
+ authTokens.Add(new AuthenticationToken { Name = "refresh_token", Value = tokens.RefreshToken });
+ }
+
+ if (!string.IsNullOrEmpty(tokens.TokenType))
+ {
+ authTokens.Add(new AuthenticationToken { Name = "token_type", Value = tokens.TokenType });
+ }
+
+ if (!string.IsNullOrEmpty(tokens.ExpiresIn))
+ {
+ int value;
+ if (int.TryParse(tokens.ExpiresIn, NumberStyles.Integer, CultureInfo.InvariantCulture, out value))
+ {
+ // https://www.w3.org/TR/xmlschema-2/#dateTime
+ // https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx
+ var expiresAt = Clock.UtcNow + TimeSpan.FromSeconds(value);
+ authTokens.Add(new AuthenticationToken
+ {
+ Name = "expires_at",
+ Value = expiresAt.ToString("o", CultureInfo.InvariantCulture)
+ });
+ }
+ }
+
+ properties.StoreTokens(authTokens);
+ }
+
+ var ticket = await CreateTicketAsync(identity, properties, tokens);
+ if (ticket != null)
+ {
+ return HandleRequestResult.Success(ticket);
+ }
+ else
+ {
+ return HandleRequestResult.Fail("Failed to retrieve user information from remote server.", properties);
+ }
+ }
+
+ protected override string FormatScope()
+ {
+ return string.Join(",", Options.Scope);
+ }
+
+ protected virtual bool IsWeChatBrowser()
+ {
+ var userAgent = Request.Headers[HeaderNames.UserAgent].ToString();
+
+ return userAgent.Contains("micromessenger", StringComparison.InvariantCultureIgnoreCase);
+ }
+ }
+}
\ No newline at end of file
diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/Microsoft/AspNetCore/Authentication/WeChat/WeChatAuthenticationOptions.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/Microsoft/AspNetCore/Authentication/WeChat/WeChatAuthenticationOptions.cs
new file mode 100644
index 000000000..9efc7600b
--- /dev/null
+++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/Microsoft/AspNetCore/Authentication/WeChat/WeChatAuthenticationOptions.cs
@@ -0,0 +1,54 @@
+using LINGYUN.Abp.WeChat.Authorization;
+using Microsoft.AspNetCore.Authentication.OAuth;
+using Microsoft.AspNetCore.Http;
+using System.Security.Claims;
+using System.Text.Json;
+
+namespace Microsoft.AspNetCore.Authentication.WeChat
+{
+ public class WeChatAuthenticationOptions : OAuthOptions
+ {
+ public string AppId
+ {
+ get => ClientId;
+ set => ClientId = value;
+ }
+
+ public string AppSecret
+ {
+ get => ClientSecret;
+ set => ClientSecret = value;
+ }
+
+ public WeChatAuthenticationOptions()
+ {
+ ClaimsIssuer = AbpWeChatAuthorizationConsts.ProviderKey;
+ CallbackPath = new PathString(AbpWeChatAuthorizationConsts.CallbackPath);
+
+ AuthorizationEndpoint = AbpWeChatAuthorizationConsts.AuthorizationEndpoint;
+ TokenEndpoint = AbpWeChatAuthorizationConsts.TokenEndpoint;
+ UserInformationEndpoint = AbpWeChatAuthorizationConsts.UserInformationEndpoint;
+
+ Scope.Add(AbpWeChatAuthorizationConsts.LoginScope);
+ Scope.Add(AbpWeChatAuthorizationConsts.UserInfoScope);
+
+ // 这个原始的属性一定要写进去,框架与UserLogin.ProviderKey进行关联判断是否绑定微信
+ ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "openid");
+ ClaimActions.MapJsonKey(ClaimTypes.Name, "nickname");
+
+ // 把自定义的身份标识写进令牌
+ ClaimActions.MapJsonKey(AbpWeChatClaimTypes.OpenId, "openid");
+ ClaimActions.MapJsonKey(AbpWeChatClaimTypes.UnionId, "unionid"); // TODO: 可用作tenant对比?
+ ClaimActions.MapJsonKey(AbpWeChatClaimTypes.NickName, "nickname");
+ ClaimActions.MapJsonKey(AbpWeChatClaimTypes.Sex, "sex", ClaimValueTypes.Integer);
+ ClaimActions.MapJsonKey(AbpWeChatClaimTypes.Country, "country");
+ ClaimActions.MapJsonKey(AbpWeChatClaimTypes.Province, "province");
+ ClaimActions.MapJsonKey(AbpWeChatClaimTypes.City, "city");
+ ClaimActions.MapJsonKey(AbpWeChatClaimTypes.AvatarUrl, "headimgurl");
+ ClaimActions.MapCustomJson(AbpWeChatClaimTypes.Privilege, user =>
+ {
+ return string.Join(",", user.GetStrings("privilege"));
+ });
+ }
+ }
+}
diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/Microsoft/AspNetCore/Authentication/WeChat/WeChatAuthenticationStateCacheItem.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/Microsoft/AspNetCore/Authentication/WeChat/WeChatAuthenticationStateCacheItem.cs
new file mode 100644
index 000000000..efc3ab3a5
--- /dev/null
+++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/Microsoft/AspNetCore/Authentication/WeChat/WeChatAuthenticationStateCacheItem.cs
@@ -0,0 +1,18 @@
+namespace Microsoft.AspNetCore.Authentication.WeChat
+{
+ public class WeChatAuthenticationStateCacheItem
+ {
+ public string State { get; set; }
+
+ public WeChatAuthenticationStateCacheItem() { }
+ public WeChatAuthenticationStateCacheItem(string state)
+ {
+ State = state;
+ }
+
+ public static string CalculateCacheKey(string correlationId, string purpose)
+ {
+ return $"ci:{correlationId};p:{purpose ?? "null"}";
+ }
+ }
+}
diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/Microsoft/AspNetCore/Authentication/WeChatAuthenticationExtensions.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/Microsoft/AspNetCore/Authentication/WeChatAuthenticationExtensions.cs
new file mode 100644
index 000000000..3fa471dc4
--- /dev/null
+++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/Microsoft/AspNetCore/Authentication/WeChatAuthenticationExtensions.cs
@@ -0,0 +1,64 @@
+using LINGYUN.Abp.WeChat.Authorization;
+using Microsoft.AspNetCore.Authentication.WeChat;
+using Microsoft.Extensions.DependencyInjection;
+using System;
+
+namespace Microsoft.AspNetCore.Authentication
+{
+ public static class WeChatAuthenticationExtensions
+ {
+ ///
+ ///
+ public static AuthenticationBuilder AddWeChat(
+ this AuthenticationBuilder builder)
+ {
+ return builder
+ .AddWeChat(
+ AbpWeChatAuthorizationConsts.AuthenticationScheme,
+ AbpWeChatAuthorizationConsts.DisplayName,
+ options => { });
+ }
+
+ ///
+ ///
+ public static AuthenticationBuilder AddWeChat(
+ this AuthenticationBuilder builder,
+ Action configureOptions)
+ {
+ return builder
+ .AddWeChat(
+ AbpWeChatAuthorizationConsts.AuthenticationScheme,
+ AbpWeChatAuthorizationConsts.DisplayName,
+ configureOptions);
+ }
+
+ ///
+ ///
+ public static AuthenticationBuilder AddWeChat(
+ this AuthenticationBuilder builder,
+ string authenticationScheme,
+ Action configureOptions)
+ {
+ return builder
+ .AddWeChat(
+ authenticationScheme,
+ AbpWeChatAuthorizationConsts.DisplayName,
+ configureOptions);
+ }
+
+ ///
+ ///
+ public static AuthenticationBuilder AddWeChat(
+ this AuthenticationBuilder builder,
+ string authenticationScheme,
+ string displayName,
+ Action configureOptions)
+ {
+ return builder
+ .AddOAuth(
+ authenticationScheme,
+ displayName,
+ configureOptions);
+ }
+ }
+}
diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/System/BytesExtensions.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/System/BytesExtensions.cs
new file mode 100644
index 000000000..d1bad7915
--- /dev/null
+++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/System/BytesExtensions.cs
@@ -0,0 +1,16 @@
+using System.Security.Cryptography;
+
+namespace System
+{
+ internal static class BytesExtensions
+ {
+ public static byte[] Sha1(this byte[] data)
+ {
+ using (var sha = SHA1.Create())
+ {
+ var hashBytes = sha.ComputeHash(data);
+ return hashBytes;
+ }
+ }
+ }
+}
diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/System/StringExtensions.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/System/StringExtensions.cs
new file mode 100644
index 000000000..a8eb40c27
--- /dev/null
+++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/System/StringExtensions.cs
@@ -0,0 +1,17 @@
+using System.Security.Cryptography;
+using System.Text;
+
+namespace System
+{
+ internal static class StringExtensions
+ {
+ public static byte[] Sha1(this string str)
+ {
+ using (var sha = SHA1.Create())
+ {
+ var hashBytes = sha.ComputeHash(Encoding.ASCII.GetBytes(str));
+ return hashBytes;
+ }
+ }
+ }
+}
diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/System/Text/Json/JsonElementExtensions.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/System/Text/Json/JsonElementExtensions.cs
new file mode 100644
index 000000000..653a868ac
--- /dev/null
+++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/System/Text/Json/JsonElementExtensions.cs
@@ -0,0 +1,63 @@
+using System.Collections.Generic;
+
+namespace System.Text.Json
+{
+ internal static class JsonElementExtensions
+ {
+ public static IEnumerable GetRootStrings(this JsonDocument json, string key)
+ {
+ return json.RootElement.GetStrings(key);
+ }
+
+ public static IEnumerable GetStrings(this JsonElement json, string key)
+ {
+ var result = new List();
+
+ if (json.TryGetProperty(key, out JsonElement property) && property.ValueKind == JsonValueKind.Array)
+ {
+ foreach (var jsonProp in property.EnumerateArray())
+ {
+ result.Add(jsonProp.GetString());
+ }
+ }
+
+ return result;
+ }
+
+ public static string GetRootString(this JsonDocument json, string key, string defaultValue = "")
+ {
+ if (json.RootElement.TryGetProperty(key, out JsonElement property))
+ {
+ return property.GetString();
+ }
+ return defaultValue;
+ }
+
+ public static string GetString(this JsonElement json, string key, string defaultValue = "")
+ {
+ if (json.TryGetProperty(key, out JsonElement property))
+ {
+ return property.GetString();
+ }
+ return defaultValue;
+ }
+
+ public static int GetRootInt32(this JsonDocument json, string key, int defaultValue = 0)
+ {
+ if (json.RootElement.TryGetProperty(key, out JsonElement property) && property.TryGetInt32(out int value))
+ {
+ return value;
+ }
+ return defaultValue;
+ }
+
+ public static int GetInt32(this JsonElement json, string key, int defaultValue = 0)
+ {
+ if (json.TryGetProperty(key, out JsonElement property) && property.TryGetInt32(out int value))
+ {
+ return value;
+ }
+ return defaultValue;
+ }
+ }
+}
diff --git a/aspnet-core/modules/wechat/LINGYUN.Abp.Notifications.WeChat/LINGYUN/Abp/Notifications/WeChat/WeApp/WeChatWeAppNotificationPublishProvider.cs b/aspnet-core/modules/wechat/LINGYUN.Abp.Notifications.WeChat/LINGYUN/Abp/Notifications/WeChat/WeApp/WeChatWeAppNotificationPublishProvider.cs
index 42f7e3b15..91136b562 100644
--- a/aspnet-core/modules/wechat/LINGYUN.Abp.Notifications.WeChat/LINGYUN/Abp/Notifications/WeChat/WeApp/WeChatWeAppNotificationPublishProvider.cs
+++ b/aspnet-core/modules/wechat/LINGYUN.Abp.Notifications.WeChat/LINGYUN/Abp/Notifications/WeChat/WeApp/WeChatWeAppNotificationPublishProvider.cs
@@ -20,8 +20,8 @@ namespace LINGYUN.Abp.Notifications.WeChat.WeApp
private IFeatureChecker _featureChecker;
protected IFeatureChecker FeatureChecker => LazyGetRequiredService(ref _featureChecker);
- private IWeChatOpenIdFinder _weChatOpenIdFinder;
- protected IWeChatOpenIdFinder WeChatOpenIdFinder => LazyGetRequiredService(ref _weChatOpenIdFinder);
+ private IUserWeChatOpenIdFinder _userWeChatOpenIdFinder;
+ protected IUserWeChatOpenIdFinder UserWeChatOpenIdFinder => LazyGetRequiredService(ref _userWeChatOpenIdFinder);
protected IWeChatWeAppNotificationSender NotificationSender { get; }
protected AbpWeChatWeAppNotificationOptions Options { get; }
@@ -79,15 +79,13 @@ namespace LINGYUN.Abp.Notifications.WeChat.WeApp
var weAppLang = GetOrDefault(notification.Data, "WeAppLanguage", Options.DefaultWeAppLanguage);
Logger.LogDebug($"Get wechat weapp language: {weAppLang ?? null}");
- // TODO: 如果微信端发布通知,请组装好 wx-code 字段在通知数据内容里面
- string weChatCode = GetOrDefault(notification.Data, "wx-code", "");
+ // TODO: 如果微信端发布通知,请组装好 openid 字段在通知数据内容里面
+ string weChatCode = GetOrDefault(notification.Data, AbpWeChatClaimTypes.OpenId, "");
- WeChatOpenId openId = weChatCode.IsNullOrWhiteSpace()
- ? await WeChatOpenIdFinder.FindByUserNameAsync(identifier.UserName) // 按照实际情况,需要自行实现 IUserWeChatCodeFinder 接口以获取微信Code,然后通过Code来获取OpenId
- : await WeChatOpenIdFinder.FindAsync(weChatCode);
-
+ var openId = !weChatCode.IsNullOrWhiteSpace() ? weChatCode
+ : await UserWeChatOpenIdFinder.FindByUserIdAsync(identifier.UserId);
- var weChatWeAppNotificationData = new WeChatWeAppSendNotificationData(openId.OpenId,
+ var weChatWeAppNotificationData = new WeChatWeAppSendNotificationData(openId,
templateId, redirect, weAppState, weAppLang);
// 写入模板数据
diff --git a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/AbpWeChatAuthorizationConsts.cs b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/AbpWeChatAuthorizationConsts.cs
new file mode 100644
index 000000000..a97731c44
--- /dev/null
+++ b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/AbpWeChatAuthorizationConsts.cs
@@ -0,0 +1,72 @@
+namespace LINGYUN.Abp.WeChat.Authorization
+{
+ ///
+ /// 与微信认证相关的静态(可变)常量
+ ///
+ public static class AbpWeChatAuthorizationConsts
+ {
+ ///
+ /// 微信授权名称
+ ///
+ public const string AuthenticationScheme = "WeChat";
+ ///
+ /// 微信授权显示名称
+ ///
+ public static string DisplayName = "WeChat";
+ ///
+ /// 微信个人信息标识
+ ///
+ public static string ProfileKey { get; set; } = "wechat.profile";
+ ///
+ /// 微信提供者标识
+ ///
+ public static string ProviderKey { get; set; } = AuthenticationScheme;
+ ///
+ /// 回调地址
+ ///
+ public static string CallbackPath { get; set; } = "/signin-wechat";
+
+ ///
+ /// 微信客户端外的网页登录
+ ///
+ public const string QrConnectEndpoint = "https://open.weixin.qq.com/connect/qrconnect";
+
+ ///
+ /// 微信客户端内的网页登录
+ ///
+ public const string AuthorizationEndpoint = "https://open.weixin.qq.com/connect/oauth2/authorize";
+
+ ///
+ /// 用户允许授权后通过返回的code换取access_token地址
+ ///
+ public const string TokenEndpoint = "https://api.weixin.qq.com/sns/oauth2/access_token";
+
+ ///
+ /// 使用access_token获取用户个人信息地址
+ ///
+ public const string UserInformationEndpoint = "https://api.weixin.qq.com/sns/userinfo";
+ ///
+ /// 弹出授权页面,可通过openid拿到昵称、性别、所在地。
+ /// 并且, 即使在未关注的情况下,只要用户授权,也能获取其信息
+ ///
+ ///
+ /// 详询:
+ ///
+ ///
+ /// 以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。
+ /// 但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息
+ ///
+ public const string UserInfoScope = "snsapi_userinfo";
+ ///
+ /// 不弹出授权页面,直接跳转,只能获取用户openid
+ ///
+ ///
+ /// 详询:
+ ///
+ ///
+ /// 以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的。
+ /// 用户感知的就是直接进入了回调页(往往是业务页面)
+ ///
+ public const string LoginScope = "snsapi_login";
+ }
+}
diff --git a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/AbpWeChatAuthorizationModule.cs b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/AbpWeChatAuthorizationModule.cs
index e69091dd7..5618c6c7d 100644
--- a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/AbpWeChatAuthorizationModule.cs
+++ b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/AbpWeChatAuthorizationModule.cs
@@ -16,7 +16,7 @@ namespace LINGYUN.Abp.WeChat.Authorization
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
- Configure(configuration.GetSection("WeChat:Auth"));
+ Configure(configuration.GetSection("WeChat:Auth"));
context.Services.AddHttpClient("WeChatRequestClient", options =>
{
diff --git a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/AbpWeChatOptions.cs b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/AbpWeChatAuthorizationOptions.cs
similarity index 76%
rename from aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/AbpWeChatOptions.cs
rename to aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/AbpWeChatAuthorizationOptions.cs
index 3c4174d9f..5c059e05b 100644
--- a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/AbpWeChatOptions.cs
+++ b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/AbpWeChatAuthorizationOptions.cs
@@ -1,6 +1,6 @@
namespace LINGYUN.Abp.WeChat.Authorization
{
- public class AbpWeChatOptions
+ public class AbpWeChatAuthorizationOptions
{
public string AppId { get; set; }
public string AppSecret { get; set; }
diff --git a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/AbpWeChatClaimTypes.cs b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/AbpWeChatClaimTypes.cs
new file mode 100644
index 000000000..58fec0452
--- /dev/null
+++ b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/AbpWeChatClaimTypes.cs
@@ -0,0 +1,48 @@
+namespace LINGYUN.Abp.WeChat.Authorization
+{
+ ///
+ /// 微信认证身份类型,可以像 自行配置
+ ///
+ /// See:
+ ///
+ public class AbpWeChatClaimTypes
+ {
+ ///
+ /// 用户的唯一标识
+ ///
+ public static string OpenId { get; set; } = "wx-openid"; // 可变更
+ ///
+ /// 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。
+ ///
+ public static string UnionId { get; set; } = "wx-unionid"; //可变更
+ ///
+ /// 用户昵称
+ ///
+ public static string NickName { get; set; } = "nickname";
+ ///
+ /// 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
+ ///
+ public static string Sex { get; set; } = "sex";
+ ///
+ /// 国家,如中国为CN
+ ///
+ public static string Country { get; set; } = "country";
+ ///
+ /// 用户个人资料填写的省份
+ ///
+ public static string Province { get; set; } = "province";
+ ///
+ /// 普通用户个人资料填写的城市
+ ///
+ public static string City { get; set; } = "city";
+ ///
+ /// 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。
+ /// 若用户更换头像,原有头像URL将失效。
+ ///
+ public static string AvatarUrl { get; set; } = "avatar";
+ ///
+ /// 用户特权信息,json 数组,如微信沃卡用户为(chinaunicom)
+ ///
+ public static string Privilege { get; set; } = "privilege";
+ }
+}
diff --git a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/OpenId/IUserWeChatCodeFinder.cs b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/OpenId/IUserWeChatOpenIdFinder.cs
similarity index 83%
rename from aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/OpenId/IUserWeChatCodeFinder.cs
rename to aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/OpenId/IUserWeChatOpenIdFinder.cs
index 1edba6807..bc56fc43c 100644
--- a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/OpenId/IUserWeChatCodeFinder.cs
+++ b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/OpenId/IUserWeChatOpenIdFinder.cs
@@ -3,7 +3,7 @@ using System.Threading.Tasks;
namespace LINGYUN.Abp.WeChat.Authorization
{
- public interface IUserWeChatCodeFinder
+ public interface IUserWeChatOpenIdFinder
{
Task FindByUserIdAsync(Guid userId);
diff --git a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/OpenId/IWeChatOpenIdFinder.cs b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/OpenId/IWeChatOpenIdFinder.cs
index 6fb15bcd9..1b548958f 100644
--- a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/OpenId/IWeChatOpenIdFinder.cs
+++ b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/OpenId/IWeChatOpenIdFinder.cs
@@ -6,9 +6,5 @@ namespace LINGYUN.Abp.WeChat.Authorization
public interface IWeChatOpenIdFinder
{
Task FindAsync(string code);
-
- Task FindByUserIdAsync(Guid userId);
-
- Task FindByUserNameAsync(string userName);
}
}
diff --git a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/OpenId/NullUserWeChatCodeFinder.cs b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/OpenId/NullUserWeChatOpenIdFinder.cs
similarity index 61%
rename from aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/OpenId/NullUserWeChatCodeFinder.cs
rename to aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/OpenId/NullUserWeChatOpenIdFinder.cs
index 364da9ef0..d05fcfbc7 100644
--- a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/OpenId/NullUserWeChatCodeFinder.cs
+++ b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/OpenId/NullUserWeChatOpenIdFinder.cs
@@ -4,16 +4,16 @@ using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.WeChat.Authorization
{
- public class NullUserWeChatCodeFinder : IUserWeChatCodeFinder, ISingletonDependency
+ public class NullUserWeChatOpenIdFinder : IUserWeChatOpenIdFinder, ISingletonDependency
{
public Task FindByUserIdAsync(Guid userId)
{
- return Task.FromResult(userId.ToString());
+ return Task.FromResult("");
}
public Task FindByUserNameAsync(string userName)
{
- return Task.FromResult(userName);
+ return Task.FromResult("");
}
}
}
diff --git a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/OpenId/WeChatOpenIdFinder.cs b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/OpenId/WeChatOpenIdFinder.cs
index fcf22aecc..a6e4b7dbc 100644
--- a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/OpenId/WeChatOpenIdFinder.cs
+++ b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/OpenId/WeChatOpenIdFinder.cs
@@ -18,23 +18,20 @@ namespace LINGYUN.Abp.WeChat.Authorization
public class WeChatOpenIdFinder : IWeChatOpenIdFinder
{
public ILogger Logger { get; set; }
- protected AbpWeChatOptions Options { get; }
+ protected AbpWeChatAuthorizationOptions Options { get; }
protected ICurrentTenant CurrentTenant { get; }
protected IHttpClientFactory HttpClientFactory { get; }
protected IJsonSerializer JsonSerializer { get; }
- protected IUserWeChatCodeFinder UserWeChatCodeFinder { get; }
protected IDistributedCache Cache { get; }
public WeChatOpenIdFinder(
ICurrentTenant currentTenant,
IJsonSerializer jsonSerializer,
- IUserWeChatCodeFinder userWeChatCodeFinder,
IHttpClientFactory httpClientFactory,
- IOptions options,
+ IOptions options,
IDistributedCache cache)
{
CurrentTenant = currentTenant;
JsonSerializer = jsonSerializer;
- UserWeChatCodeFinder = userWeChatCodeFinder;
HttpClientFactory = httpClientFactory;
Cache = cache;
@@ -49,24 +46,6 @@ namespace LINGYUN.Abp.WeChat.Authorization
return (await GetCacheItemAsync(code)).WeChatOpenId;
}
- public virtual async Task FindByUserIdAsync(Guid userId)
- {
- var code = await UserWeChatCodeFinder.FindByUserIdAsync(userId);
- // TODO: 如果需要获取SessionKey的话呢,需要再以openid作为标识来缓存一下吗
- // 或者前端保存code,通过传递code来获取
- return (await GetCacheItemAsync(code)).WeChatOpenId;
- }
-
- public virtual async Task FindByUserNameAsync(string userName)
- {
- var code = await UserWeChatCodeFinder.FindByUserNameAsync(userName);
- // TODO: 如果需要获取SessionKey的话呢,需要再以openid作为标识来缓存一下吗
- // 或者前端保存code,通过传递code来获取
- return (await GetCacheItemAsync(code)).WeChatOpenId;
- }
-
-
-
protected virtual async Task GetCacheItemAsync(string code)
{
var cacheKey = WeChatOpenIdCacheItem.CalculateCacheKey(code);
diff --git a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/Token/WeChatTokenProvider.cs b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/Token/WeChatTokenProvider.cs
index 4e1cb40e5..6df509537 100644
--- a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/Token/WeChatTokenProvider.cs
+++ b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/Token/WeChatTokenProvider.cs
@@ -18,11 +18,11 @@ namespace LINGYUN.Abp.WeChat.Authorization
protected IHttpClientFactory HttpClientFactory { get; }
protected IJsonSerializer JsonSerializer { get; }
protected IDistributedCache Cache { get; }
- protected AbpWeChatOptions Options { get; }
+ protected AbpWeChatAuthorizationOptions Options { get; }
public WeChatTokenProvider(
IJsonSerializer jsonSerializer,
IHttpClientFactory httpClientFactory,
- IOptions options,
+ IOptions options,
IDistributedCache cache)
{
JsonSerializer = jsonSerializer;
diff --git a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/WeChatAuthorizationConsts.cs b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/WeChatAuthorizationConsts.cs
deleted file mode 100644
index d1ffc1a13..000000000
--- a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/LINGYUN/Abp/WeChat/Authorization/WeChatAuthorizationConsts.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-namespace LINGYUN.Abp.WeChat.Authorization
-{
- public class WeChatAuthorizationConsts
- {
- ///
- /// 微信提供者标识
- ///
- public static string ProviderKey { get; set; } = "WeChat";
- ///
- /// 微信Code参数名称
- ///
- public static string WeCahtCodeKey { get; set; } = "wx-code";
- ///
- /// 微信OpenId参数名称
- ///
- public static string WeCahtOpenIdKey { get; set; } = "wx-open-id";
- ///
- /// 微信SessionKey参数名称
- ///
- public static string WeCahtSessionKey { get; set; } = "wx-session-key";
- }
-}
diff --git a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/Volo/Abp/Security/Claims/WeChatClaimTypes.cs b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/Volo/Abp/Security/Claims/WeChatClaimTypes.cs
deleted file mode 100644
index 792813c49..000000000
--- a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/Volo/Abp/Security/Claims/WeChatClaimTypes.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-namespace Volo.Abp.Security.Claims
-{
- public class WeChatClaimTypes
- {
- public static string OpenId { get; set; } = "wx-openid";
- public static string UnionId { get; set; } = "wx-unionid";
- }
-}
diff --git a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/Volo/Abp/Users/CurrentUserExtensions.cs b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/Volo/Abp/Users/CurrentUserExtensions.cs
index b3a68ea18..bf9c16cad 100644
--- a/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/Volo/Abp/Users/CurrentUserExtensions.cs
+++ b/aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Authorization/Volo/Abp/Users/CurrentUserExtensions.cs
@@ -1,4 +1,4 @@
-using Volo.Abp.Security.Claims;
+using LINGYUN.Abp.WeChat.Authorization;
namespace Volo.Abp.Users
{
@@ -11,7 +11,7 @@ namespace Volo.Abp.Users
///
public static string FindWeChatOpenId(this ICurrentUser currentUser)
{
- var weChatClaim = currentUser.FindClaim(WeChatClaimTypes.OpenId);
+ var weChatClaim = currentUser.FindClaim(AbpWeChatClaimTypes.OpenId);
if (weChatClaim == null)
{
return null;
@@ -27,7 +27,7 @@ namespace Volo.Abp.Users
///
public static string FindWeChatUnionId(this ICurrentUser currentUser)
{
- var weChatClaim = currentUser.FindClaim(WeChatClaimTypes.UnionId);
+ var weChatClaim = currentUser.FindClaim(AbpWeChatClaimTypes.UnionId);
if (weChatClaim == null)
{
return null;
diff --git a/aspnet-core/services/account/AuthServer.Host/AuthIdentityServerModule.cs b/aspnet-core/services/account/AuthServer.Host/AuthIdentityServerModule.cs
index 54d45ee68..687c2c696 100644
--- a/aspnet-core/services/account/AuthServer.Host/AuthIdentityServerModule.cs
+++ b/aspnet-core/services/account/AuthServer.Host/AuthIdentityServerModule.cs
@@ -3,6 +3,7 @@ using LINGYUN.Abp.EventBus.CAP;
using LINGYUN.Abp.IdentityServer;
using LINGYUN.Abp.MultiTenancy.DbFinder;
using LINGYUN.Abp.PermissionManagement.Identity;
+using Microsoft.AspNetCore.Authentication.WeChat;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.DataProtection;
@@ -114,6 +115,11 @@ namespace AuthServer.Host
options.InitVectorBytes = encryptionConfiguration.GetSection("InitVector").Exists()
? Encoding.ASCII.GetBytes(encryptionConfiguration["InitVector"])
: options.InitVectorBytes;
+
+ var keySizeConfig = encryptionConfiguration.GetSection("Keysize");
+ options.Keysize = keySizeConfig.Exists()
+ ? keySizeConfig.Get()
+ : options.Keysize;
}
});
@@ -216,10 +222,11 @@ namespace AuthServer.Host
app.UseVirtualFiles();
app.UseRouting();
app.UseCors(DefaultCorsPolicyName);
+ app.UseWeChatSignature();
+ app.UseMultiTenancy();
app.UseAuthentication();
app.UseJwtTokenMiddleware();
app.UseAbpClaimsMap();
- app.UseMultiTenancy();
app.UseAbpRequestLocalization();
app.UseIdentityServer();
app.UseAuthorization();
diff --git a/aspnet-core/services/account/AuthServer.Host/DataSeeder/IdentityServerDataSeedContributor.cs b/aspnet-core/services/account/AuthServer.Host/DataSeeder/IdentityServerDataSeedContributor.cs
index b28a8e9a8..18feae7bd 100644
--- a/aspnet-core/services/account/AuthServer.Host/DataSeeder/IdentityServerDataSeedContributor.cs
+++ b/aspnet-core/services/account/AuthServer.Host/DataSeeder/IdentityServerDataSeedContributor.cs
@@ -1,4 +1,5 @@
-using Microsoft.Extensions.Configuration;
+using LINGYUN.Abp.IdentityServer;
+using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.IO;
@@ -13,7 +14,6 @@ using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.IdentityServer.IdentityResources;
using Volo.Abp.PermissionManagement;
-using Volo.Abp.Security.Claims;
using Volo.Abp.Uow;
namespace AuthServer.DataSeeder
@@ -25,6 +25,7 @@ namespace AuthServer.DataSeeder
private readonly IIdentityResourceDataSeeder _identityResourceDataSeeder;
private readonly IIdentityClaimTypeRepository _identityClaimTypeRepository;
private readonly IPermissionDataSeeder _permissionDataSeeder;
+ private readonly IWeChatResourceDataSeeder _weChatResourceDataSeeder;
private readonly IGuidGenerator _guidGenerator;
private readonly IConfiguration _configuration;
@@ -32,6 +33,7 @@ namespace AuthServer.DataSeeder
IClientRepository clientRepository,
IPermissionDataSeeder permissionDataSeeder,
IApiResourceRepository apiResourceRepository,
+ IWeChatResourceDataSeeder weChatResourceDataSeeder,
IIdentityResourceDataSeeder identityResourceDataSeeder,
IIdentityClaimTypeRepository identityClaimTypeRepository,
IGuidGenerator guidGenerator)
@@ -40,6 +42,7 @@ namespace AuthServer.DataSeeder
_permissionDataSeeder = permissionDataSeeder;
_apiResourceRepository = apiResourceRepository;
_identityClaimTypeRepository = identityClaimTypeRepository;
+ _weChatResourceDataSeeder = weChatResourceDataSeeder;
_identityResourceDataSeeder = identityResourceDataSeeder;
_guidGenerator = guidGenerator;
var env = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production";
@@ -62,13 +65,7 @@ namespace AuthServer.DataSeeder
private async Task CreateWeChatClaimTypeAsync()
{
- if (!await _identityClaimTypeRepository.AnyAsync(WeChatClaimTypes.OpenId))
- {
- var wechatClaimType = new IdentityClaimType(_guidGenerator.Create(), WeChatClaimTypes.OpenId,
- isStatic: true, description: "适用于微信认证的用户标识");
-
- await _identityClaimTypeRepository.InsertAsync(wechatClaimType);
- }
+ await _weChatResourceDataSeeder.CreateStandardResourcesAsync();
}
private async Task CreateApiResourcesAsync()
diff --git a/aspnet-core/services/account/AuthServer.Host/Microsoft/Extensions/DependencyInjection/SameSiteCookiesServiceCollectionExtensions.cs b/aspnet-core/services/account/AuthServer.Host/Microsoft/Extensions/DependencyInjection/SameSiteCookiesServiceCollectionExtensions.cs
index b7a2b72bb..9847bd905 100644
--- a/aspnet-core/services/account/AuthServer.Host/Microsoft/Extensions/DependencyInjection/SameSiteCookiesServiceCollectionExtensions.cs
+++ b/aspnet-core/services/account/AuthServer.Host/Microsoft/Extensions/DependencyInjection/SameSiteCookiesServiceCollectionExtensions.cs
@@ -146,7 +146,13 @@ namespace Microsoft.Extensions.DependencyInjection
{
try
{
- return Convert.ToInt32(userAgent.Split("Chrome/")[1].Split('.')[0]);
+ string version = "0";
+ var chromeAgents = userAgent.Split("Chrome/");
+ if (chromeAgents.Length > 1 && chromeAgents[1].Split('.').Length > 0)
+ {
+ version = chromeAgents[1].Split('.')[0];
+ }
+ return Convert.ToInt32(version);
}
catch (Exception)
{
@@ -154,4 +160,4 @@ namespace Microsoft.Extensions.DependencyInjection
}
}
}
-}
+}
\ No newline at end of file