Browse Source

remove useless modules

pull/712/head
cKey 3 years ago
parent
commit
ba4c8cb156
  1. 3
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.QQ/FodyWeavers.xml
  2. 30
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.QQ/FodyWeavers.xsd
  3. 19
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.QQ/LINGYUN.Abp.IdentityServer.QQ.csproj
  4. 8
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.QQ/LINGYUN/Abp/IdentityServer/QQ/AbpIdentityServerQQConsts.cs
  5. 19
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.QQ/LINGYUN/Abp/IdentityServer/QQ/AbpIdentityServerQQModule.cs
  6. 31
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.QQ/LINGYUN/Abp/IdentityServer/QQ/AbpQQClaimTypes.cs
  7. 175
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.QQ/Microsoft/AspNetCore/Authentication/QQ/QQConnectOAuthHandler.cs
  8. 47
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.QQ/Microsoft/AspNetCore/Authentication/QQ/QQConnectOAuthOptions.cs
  9. 63
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.QQ/Microsoft/AspNetCore/Authentication/QQAuthenticationExtensions.cs
  10. 16
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.QQ/System/BytesExtensions.cs
  11. 17
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.QQ/System/StringExtensions.cs
  12. 63
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.QQ/System/Text/Json/JsonElementExtensions.cs
  13. 3
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/FodyWeavers.xml
  14. 30
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/FodyWeavers.xsd
  15. 26
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN.Abp.IdentityServer.WeChat.csproj
  16. 56
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/AbpIdentityServerWeChatModule.cs
  17. 9
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/IWeChatResourceDataSeeder.cs
  18. 12
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/Localization/en.json
  19. 12
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/Localization/zh-Hans.json
  20. 75
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/MiniProgram/WeChatMiniProgramGrantValidator.cs
  21. 67
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/MiniProgram/WeChatMiniProgramProfileService.cs
  22. 75
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/Official/WeChatOfficialGrantValidator.cs
  23. 71
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/Official/WeChatOfficialOAuthConsts.cs
  24. 77
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/Official/WeChatOfficialSignatureMiddleware.cs
  25. 242
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/WeChatGrantValidator.cs
  26. 86
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/WeChatResourceDataSeeder.cs
  27. 336
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/Microsoft/AspNetCore/Authentication/WeChat/Official/WeChatOfficialOAuthHandler.cs
  28. 47
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/Microsoft/AspNetCore/Authentication/WeChat/Official/WeChatOfficialOAuthOptions.cs
  29. 18
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/Microsoft/AspNetCore/Authentication/WeChat/Official/WeChatOfficialStateCacheItem.cs
  30. 65
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/Microsoft/AspNetCore/Authentication/WeChatAuthenticationExtensions.cs
  31. 22
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/Microsoft/AspNetCore/Builder/IdentityServerApplicationBuilderExtensions.cs
  32. 16
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/System/BytesExtensions.cs
  33. 17
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/System/StringExtensions.cs
  34. 63
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/System/Text/Json/JsonElementExtensions.cs

3
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.QQ/FodyWeavers.xml

@ -1,3 +0,0 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.QQ/FodyWeavers.xsd

@ -1,30 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

19
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.QQ/LINGYUN.Abp.IdentityServer.QQ.csproj

@ -1,19 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.props" />
<Import Project="..\..\..\configureawait.props" />
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.IdentityServer.Domain" Version="$(VoloAbpPackageVersion)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\cloud-tencent\LINGYUN.Abp.Tencent.QQ\LINGYUN.Abp.Tencent.QQ.csproj" />
</ItemGroup>
</Project>

8
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.QQ/LINGYUN/Abp/IdentityServer/QQ/AbpIdentityServerQQConsts.cs

@ -1,8 +0,0 @@
namespace LINGYUN.Abp.IdentityServer.QQ;
public static class AbpIdentityServerQQConsts
{
public static string AuthenticationScheme { get; set; } = "QQ Connect";
public static string DisplayName { get; set; } = "QQ Connect";
public static string CallbackPath { get; set; } = "/signin-qq";
}

19
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.QQ/LINGYUN/Abp/IdentityServer/QQ/AbpIdentityServerQQModule.cs

@ -1,19 +0,0 @@
using LINGYUN.Abp.Tencent.QQ;
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.IdentityServer;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.IdentityServer.QQ;
[DependsOn(typeof(AbpTencentQQModule))]
[DependsOn(typeof(AbpIdentityServerDomainModule))]
public class AbpIdentityServerQQModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services
.AddAuthentication()
.AddQQConnect();
}
}

31
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.QQ/LINGYUN/Abp/IdentityServer/QQ/AbpQQClaimTypes.cs

@ -1,31 +0,0 @@
namespace LINGYUN.Abp.WeChat.Security.Claims
{
/// <summary>
/// QQ互联身份类型,可以像 <see cref="Volo.Abp.Security.Claims.AbpClaimTypes"/> 自行配置
/// <br />
/// See: <see cref="https://wiki.connect.qq.com/get_user_info"/>
/// </summary>
public class AbpQQClaimTypes
{
/// <summary>
/// 用户的唯一标识
/// </summary>
public static string OpenId { get; set; } = "qq-openid"; // 可变更
/// <summary>
/// 用户昵称
/// </summary>
public static string NickName { get; set; } = "nickname";
/// <summary>
/// 性别。 如果获取不到则默认返回"男"
/// </summary>
public static string Gender { get; set; } = "gender";
/// <summary>
/// 用户头像, 取自字段: figureurl_qq_1
/// </summary>
/// <remarks>
/// 根据QQ互联文档, 40x40的头像是一定会存在的, 只取40x40的头像
/// see: https://wiki.connect.qq.com/get_user_info
/// </remarks>
public static string AvatarUrl { get; set; } = "avatar";
}
}

175
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.QQ/Microsoft/AspNetCore/Authentication/QQ/QQConnectOAuthHandler.cs

@ -1,175 +0,0 @@
using LINGYUN.Abp.Tencent.QQ;
using LINGYUN.Abp.WeChat.Security.Claims;
using Microsoft.AspNetCore.Authentication.OAuth;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Claims;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Threading.Tasks;
namespace Microsoft.AspNetCore.Authentication.QQ
{
/// <summary>
/// QQ互联实现
/// </summary>
public class QQConnectOAuthHandler : OAuthHandler<QQConnectOAuthOptions>
{
protected AbpTencentQQOptionsFactory TencentQQOptionsFactory { get; }
public QQConnectOAuthHandler(
IOptionsMonitor<QQConnectOAuthOptions> options,
AbpTencentQQOptionsFactory tencentQQOptionsFactory,
ILoggerFactory logger,
UrlEncoder encoder,
ISystemClock clock)
: base(options, logger, encoder, clock)
{
TencentQQOptionsFactory = tencentQQOptionsFactory;
}
protected override async Task InitializeHandlerAsync()
{
var options = await TencentQQOptionsFactory.CreateAsync();
// 用配置项重写
Options.ClientId = options.AppId;
Options.ClientSecret = options.AppKey;
Options.IsMobile = options.IsMobile;
await base.InitializeHandlerAsync();
}
/// <summary>
/// 构建用户授权地址
/// </summary>
protected override string BuildChallengeUrl(AuthenticationProperties properties, string redirectUri)
{
var challengeUrl = base.BuildChallengeUrl(properties, redirectUri);
if (Options.IsMobile)
{
challengeUrl += "&display=mobile";
}
return challengeUrl;
}
/// <summary>
/// code换取access_token
/// </summary>
protected override async Task<OAuthTokenResponse> ExchangeCodeAsync(OAuthCodeExchangeContext context)
{
var address = QueryHelpers.AddQueryString(Options.TokenEndpoint, new Dictionary<string, string>()
{
{ "client_id", Options.ClientId },
{ "redirect_uri", context.RedirectUri },
{ "client_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<AuthenticationTicket> CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens)
{
var openIdEndpoint = Options.OpenIdEndpoint + "?access_token=" + tokens.AccessToken + "&fmt=json";
var openIdResponse = await Backchannel.GetAsync(openIdEndpoint, Context.RequestAborted);
openIdResponse.EnsureSuccessStatusCode();
var openIdPayload = JsonDocument.Parse(await openIdResponse.Content.ReadAsStringAsync());
var openId = openIdPayload.GetRootString("openid");
identity.AddClaim(new Claim(AbpQQClaimTypes.OpenId, openId, ClaimValueTypes.String, Options.ClaimsIssuer));
var address = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, new Dictionary<string, string>
{
{"oauth_consumer_key", Options.ClientId},
{"access_token", tokens.AccessToken},
{"openid", 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 userInfoPayload = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
var errorCode = userInfoPayload.GetRootString("ret");
if (!"0".Equals(errorCode))
{
// See: https://wiki.connect.qq.com/%e5%85%ac%e5%85%b1%e8%bf%94%e5%9b%9e%e7%a0%81%e8%af%b4%e6%98%8e
Logger.LogError("An error occurred while retrieving the user profile: the remote server " +
"returned code {Code} response with message: {Message}.",
errorCode,
userInfoPayload.GetRootString("msg"));
throw new HttpRequestException("An error occurred while retrieving user information.");
}
var nickName = userInfoPayload.GetRootString("nickname");
if (!nickName.IsNullOrWhiteSpace())
{
identity.AddClaim(new Claim(AbpQQClaimTypes.NickName, nickName, ClaimValueTypes.String, Options.ClaimsIssuer));
}
var gender = userInfoPayload.GetRootString("gender");
if (!gender.IsNullOrWhiteSpace())
{
identity.AddClaim(new Claim(AbpQQClaimTypes.Gender, gender, ClaimValueTypes.String, Options.ClaimsIssuer));
}
var avatarUrl = userInfoPayload.GetRootString("figureurl_qq_1");
if (!avatarUrl.IsNullOrWhiteSpace())
{
identity.AddClaim(new Claim(AbpQQClaimTypes.AvatarUrl, avatarUrl, ClaimValueTypes.String, Options.ClaimsIssuer));
}
var context = new OAuthCreatingTicketContext(
new ClaimsPrincipal(identity),
properties,
Context,
Scheme,
Options,
Backchannel,
tokens,
userInfoPayload.RootElement);
context.RunClaimActions();
await Events.CreatingTicket(context);
return new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name);
}
}
}

47
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.QQ/Microsoft/AspNetCore/Authentication/QQ/QQConnectOAuthOptions.cs

@ -1,47 +0,0 @@
using LINGYUN.Abp.IdentityServer.QQ;
using LINGYUN.Abp.WeChat.Security.Claims;
using Microsoft.AspNetCore.Authentication.OAuth;
using Microsoft.AspNetCore.Http;
using System.Security.Claims;
namespace Microsoft.AspNetCore.Authentication.QQ
{
public class QQConnectOAuthOptions : OAuthOptions
{
/// <summary>
/// 是否移动端样式
/// </summary>
public bool IsMobile { get; set; }
/// <summary>
/// 获取用户OpenID_OAuth2.0
/// </summary>
public string OpenIdEndpoint { get; set; }
public QQConnectOAuthOptions()
{
// 用于防止初始化错误,会在OAuthHandler.InitializeHandlerAsync中进行重写
ClientId = "QQConnect";
ClientSecret = "QQConnect";
ClaimsIssuer = "connect.qq.com";
CallbackPath = new PathString(AbpIdentityServerQQConsts.CallbackPath);
AuthorizationEndpoint = "https://graph.qq.com/oauth2.0/authorize";
TokenEndpoint = "https://graph.qq.com/oauth2.0/token";
OpenIdEndpoint = "https://graph.qq.com/oauth2.0/me";
UserInformationEndpoint = "https://graph.qq.com/user/get_user_info";
Scope.Add("get_user_info");
// 这个原始的属性一定要写进去,框架关联判断是否绑定QQ
ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "openid");
ClaimActions.MapJsonKey(ClaimTypes.Name, "nickname");
// 把自定义的身份标识写进令牌
ClaimActions.MapJsonKey(AbpQQClaimTypes.OpenId, "openid");
ClaimActions.MapJsonKey(AbpQQClaimTypes.NickName, "nickname");
ClaimActions.MapJsonKey(AbpQQClaimTypes.Gender, "gender");
ClaimActions.MapJsonKey(AbpQQClaimTypes.AvatarUrl, "figureurl_qq_1");
}
}
}

63
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.QQ/Microsoft/AspNetCore/Authentication/QQAuthenticationExtensions.cs

@ -1,63 +0,0 @@
using LINGYUN.Abp.IdentityServer.QQ;
using Microsoft.AspNetCore.Authentication.QQ;
using Microsoft.Extensions.DependencyInjection;
using System;
namespace Microsoft.AspNetCore.Authentication
{
public static class QQAuthenticationExtensions
{
/// <summary>
/// </summary>
public static AuthenticationBuilder AddQQConnect(
this AuthenticationBuilder builder)
{
return builder
.AddQQConnect(
AbpIdentityServerQQConsts.AuthenticationScheme,
AbpIdentityServerQQConsts.DisplayName,
options => { });
}
/// <summary>
/// </summary>
public static AuthenticationBuilder AddQQConnect(
this AuthenticationBuilder builder,
Action<QQConnectOAuthOptions> configureOptions)
{
return builder
.AddQQConnect(
AbpIdentityServerQQConsts.AuthenticationScheme,
configureOptions);
}
/// <summary>
/// </summary>
public static AuthenticationBuilder AddQQConnect(
this AuthenticationBuilder builder,
string authenticationScheme,
Action<QQConnectOAuthOptions> configureOptions)
{
return builder
.AddQQConnect(
authenticationScheme,
AbpIdentityServerQQConsts.DisplayName,
configureOptions);
}
/// <summary>
/// </summary>
public static AuthenticationBuilder AddQQConnect(
this AuthenticationBuilder builder,
string authenticationScheme,
string displayName,
Action<QQConnectOAuthOptions> configureOptions)
{
return builder
.AddOAuth<QQConnectOAuthOptions, QQConnectOAuthHandler>(
authenticationScheme,
displayName,
configureOptions);
}
}
}

16
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.QQ/System/BytesExtensions.cs

@ -1,16 +0,0 @@
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;
}
}
}
}

17
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.QQ/System/StringExtensions.cs

@ -1,17 +0,0 @@
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;
}
}
}
}

63
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.QQ/System/Text/Json/JsonElementExtensions.cs

@ -1,63 +0,0 @@
using System.Collections.Generic;
namespace System.Text.Json
{
internal static class JsonElementExtensions
{
public static IEnumerable<string> GetRootStrings(this JsonDocument json, string key)
{
return json.RootElement.GetStrings(key);
}
public static IEnumerable<string> GetStrings(this JsonElement json, string key)
{
var result = new List<string>();
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;
}
}
}

3
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/FodyWeavers.xml

@ -1,3 +0,0 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/FodyWeavers.xsd

@ -1,30 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

26
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN.Abp.IdentityServer.WeChat.csproj

@ -1,26 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.props" />
<Import Project="..\..\..\configureawait.props" />
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="LINGYUN\Abp\IdentityServer\WeChat\Localization\en.json" />
<EmbeddedResource Include="LINGYUN\Abp\IdentityServer\WeChat\Localization\zh-Hans.json" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.IdentityServer.Domain" Version="$(VoloAbpPackageVersion)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\wechat\LINGYUN.Abp.Identity.WeChat\LINGYUN.Abp.Identity.WeChat.csproj" />
<ProjectReference Include="..\..\wechat\LINGYUN.Abp.WeChat.MiniProgram\LINGYUN.Abp.WeChat.MiniProgram.csproj" />
<ProjectReference Include="..\..\wechat\LINGYUN.Abp.WeChat.Official\LINGYUN.Abp.WeChat.Official.csproj" />
</ItemGroup>
</Project>

56
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/AbpIdentityServerWeChatModule.cs

@ -1,56 +0,0 @@
using LINGYUN.Abp.Identity.WeChat;
using LINGYUN.Abp.IdentityServer.WeChat.MiniProgram;
using LINGYUN.Abp.IdentityServer.WeChat.Official;
using LINGYUN.Abp.WeChat.MiniProgram;
using LINGYUN.Abp.WeChat.Official;
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.IdentityServer;
using Volo.Abp.IdentityServer.Localization;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem;
namespace LINGYUN.Abp.IdentityServer.WeChat
{
[DependsOn(
typeof(AbpWeChatOfficialModule),
typeof(AbpWeChatMiniProgramModule),
typeof(AbpIdentityWeChatModule),
typeof(AbpIdentityServerDomainModule))]
public class AbpIdentityServerWeChatModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
PreConfigure<IIdentityServerBuilder>(builder =>
{
builder.AddProfileService<WeChatMiniProgramProfileService>();
// TODO: 两个类型不通用配置项,不然只需要一个
builder.AddExtensionGrantValidator<WeChatMiniProgramGrantValidator>();
builder.AddExtensionGrantValidator<WeChatOfficialGrantValidator>();
});
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpIdentityServerWeChatModule>();
});
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Get<AbpIdentityServerResource>()
.AddVirtualJson("/LINGYUN/Abp/IdentityServer/WeChat/Localization");
});
context.Services
.AddAuthentication()
.AddWeChat();
}
}
}

9
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/IWeChatResourceDataSeeder.cs

@ -1,9 +0,0 @@
using System.Threading.Tasks;
namespace LINGYUN.Abp.IdentityServer
{
public interface IWeChatResourceDataSeeder
{
Task CreateStandardResourcesAsync();
}
}

12
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/Localization/en.json

@ -1,12 +0,0 @@
{
"culture": "en",
"texts": {
"MiniProgramAuthorizationDisabledMessage": "Applet authorization is not enabled for the application",
"OfficialAuthorizationDisabledMessage": "Official authorization is not enabled for the application",
"SelfRegistrationDisabledMessage": "Self-registration is disabled for this application. Please contact the application administrator to register a new user.",
"InvalidGrant:GrantTypeInvalid": "The type of authorization that is not allowed!",
"InvalidGrant:WeChatTokenInvalid": "WeChat authentication failed!",
"InvalidGrant:WeChatCodeNotFound": "The code obtained when WeChat is logged in is empty or does not exist!",
"InvalidGrant:WeChatNotRegister": "User WeChat account not registed!"
}
}

12
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/Localization/zh-Hans.json

@ -1,12 +0,0 @@
{
"culture": "zh-Hans",
"texts": {
"MiniProgramAuthorizationDisabledMessage": "应用程序未开放小程序授权",
"OfficialAuthorizationDisabledMessage": "应用程序未开放公众平台授权",
"SelfRegistrationDisabledMessage": "应用程序未开放注册,请联系管理员添加新用户.",
"InvalidGrant:GrantTypeInvalid": "不被允许的授权类型!",
"InvalidGrant:WeChatTokenInvalid": "微信认证失败!",
"InvalidGrant:WeChatCodeNotFound": "微信登录时获取的 code 为空或不存在!",
"InvalidGrant:WeChatNotRegister": "用户微信账号未绑定!"
}
}

75
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/MiniProgram/WeChatMiniProgramGrantValidator.cs

@ -1,75 +0,0 @@
using IdentityServer4.Models;
using IdentityServer4.Services;
using IdentityServer4.Validation;
using LINGYUN.Abp.WeChat.Localization;
using LINGYUN.Abp.WeChat.MiniProgram;
using LINGYUN.Abp.WeChat.MiniProgram.Features;
using LINGYUN.Abp.WeChat.OpenId;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Localization;
using System.Threading.Tasks;
using Volo.Abp.Features;
using Volo.Abp.Identity;
using Volo.Abp.IdentityServer.Localization;
using IdentityUser = Volo.Abp.Identity.IdentityUser;
namespace LINGYUN.Abp.IdentityServer.WeChat.MiniProgram
{
/// <summary>
/// 对于小程序绑定用户的扩展授权验证器
/// </summary>
public class WeChatMiniProgramGrantValidator : WeChatGrantValidator
{
public override string GrantType => AbpWeChatMiniProgramConsts.GrantType;
public override string LoginProvider => AbpWeChatMiniProgramConsts.ProviderName;
public override string AuthenticationMethod => AbpWeChatMiniProgramConsts.AuthenticationMethod;
protected AbpWeChatMiniProgramOptionsFactory MiniProgramOptionsFactory { get; }
protected IFeatureChecker FeatureChecker => ServiceProvider.LazyGetRequiredService<IFeatureChecker>();
public WeChatMiniProgramGrantValidator(
IEventService eventService,
IWeChatOpenIdFinder weChatOpenIdFinder,
UserManager<IdentityUser> userManager,
IIdentityUserRepository userRepository,
IdentitySecurityLogManager identitySecurityLogManager,
IStringLocalizer<Volo.Abp.Identity.Localization.IdentityResource> identityLocalizer,
IStringLocalizer<AbpIdentityServerResource> identityServerLocalizer,
IStringLocalizer<WeChatResource> wechatLocalizer,
AbpWeChatMiniProgramOptionsFactory miniProgramOptionsFactory)
: base(
eventService,
weChatOpenIdFinder,
userManager,
userRepository,
identitySecurityLogManager,
wechatLocalizer,
identityLocalizer,
identityServerLocalizer)
{
MiniProgramOptionsFactory = miniProgramOptionsFactory;
}
protected override async Task<bool> CheckFeatureAsync(ExtensionGrantValidationContext context)
{
if (!await FeatureChecker.IsEnabledAsync(WeChatMiniProgramFeatures.EnableAuthorization))
{
context.Result = new GrantValidationResult(
TokenRequestErrors.InvalidGrant,
WeChatLocalizer["MiniProgramAuthorizationDisabledMessage"]);
return false;
}
return true;
}
protected override async Task<WeChatOpenId> FindOpenIdAsync(string code)
{
var options = await MiniProgramOptionsFactory.CreateAsync();
return await WeChatOpenIdFinder.FindAsync(code, options.AppId, options.AppSecret);
}
}
}

67
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/MiniProgram/WeChatMiniProgramProfileService.cs

@ -1,67 +0,0 @@
using IdentityServer4.AspNetIdentity;
using IdentityServer4.Models;
using LINGYUN.Abp.WeChat.Security.Claims;
using Microsoft.AspNetCore.Identity;
using System.Linq;
using System.Security.Principal;
using System.Threading.Tasks;
using Volo.Abp.Identity;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Uow;
using IdentityUser = Volo.Abp.Identity.IdentityUser;
namespace LINGYUN.Abp.IdentityServer.WeChat.MiniProgram
{
public class WeChatMiniProgramProfileService : ProfileService<IdentityUser>
{
protected ICurrentTenant CurrentTenant { get; }
public WeChatMiniProgramProfileService(
IdentityUserManager userManager,
IUserClaimsPrincipalFactory<IdentityUser> claimsFactory,
ICurrentTenant currentTenant)
: base(userManager, claimsFactory)
{
CurrentTenant = currentTenant;
}
[UnitOfWork]
public override async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
using (CurrentTenant.Change(context.Subject.FindTenantId()))
{
await base.GetProfileDataAsync(context);
// TODO: 可以从令牌获取openid, 安全性呢?
TryAddWeChatClaim(context, AbpWeChatClaimTypes.OpenId);
TryAddWeChatClaim(context, AbpWeChatClaimTypes.UnionId);
}
}
[UnitOfWork]
public override async Task IsActiveAsync(IsActiveContext context)
{
using (CurrentTenant.Change(context.Subject.FindTenantId()))
{
await base.IsActiveAsync(context);
}
}
[UnitOfWork]
public override Task<bool> IsUserActiveAsync(IdentityUser user)
{
return Task.FromResult(user.IsActive);
}
protected virtual void TryAddWeChatClaim(ProfileDataRequestContext context, string weChatClaimType)
{
if (context.RequestedClaimTypes.Any(rc => rc.Contains(weChatClaimType)))
{
var weChatClaim = context.Subject.FindFirst(weChatClaimType);
if (weChatClaim != null)
{
context.IssuedClaims.Add(weChatClaim);
}
}
}
}
}

75
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/Official/WeChatOfficialGrantValidator.cs

@ -1,75 +0,0 @@
using IdentityServer4.Models;
using IdentityServer4.Services;
using IdentityServer4.Validation;
using LINGYUN.Abp.WeChat.Localization;
using LINGYUN.Abp.WeChat.Official;
using LINGYUN.Abp.WeChat.Official.Features;
using LINGYUN.Abp.WeChat.OpenId;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Localization;
using System.Threading.Tasks;
using Volo.Abp.Features;
using Volo.Abp.Identity;
using Volo.Abp.IdentityServer.Localization;
using IdentityUser = Volo.Abp.Identity.IdentityUser;
namespace LINGYUN.Abp.IdentityServer.WeChat.Official
{
/// <summary>
/// 对于公众平台绑定用户的扩展授权验证器
/// </summary>
public class WeChatOfficialGrantValidator : WeChatGrantValidator
{
public override string GrantType => AbpWeChatOfficialConsts.GrantType;
public override string LoginProvider => AbpWeChatOfficialConsts.ProviderName;
public override string AuthenticationMethod => AbpWeChatOfficialConsts.AuthenticationMethod;
protected AbpWeChatOfficialOptionsFactory WeChatOfficialOptionsFactory { get; }
protected IFeatureChecker FeatureChecker => ServiceProvider.LazyGetRequiredService<IFeatureChecker>();
public WeChatOfficialGrantValidator(
IEventService eventService,
IWeChatOpenIdFinder weChatOpenIdFinder,
UserManager<IdentityUser> userManager,
IIdentityUserRepository userRepository,
IdentitySecurityLogManager identitySecurityLogManager,
IStringLocalizer<Volo.Abp.Identity.Localization.IdentityResource> identityLocalizer,
IStringLocalizer<AbpIdentityServerResource> identityServerLocalizer,
IStringLocalizer<WeChatResource> wechatLocalizer,
AbpWeChatOfficialOptionsFactory weChatOfficialOptionsFactory)
: base(
eventService,
weChatOpenIdFinder,
userManager,
userRepository,
identitySecurityLogManager,
wechatLocalizer,
identityLocalizer,
identityServerLocalizer)
{
WeChatOfficialOptionsFactory = weChatOfficialOptionsFactory;
}
protected override async Task<bool> CheckFeatureAsync(ExtensionGrantValidationContext context)
{
if (!await FeatureChecker.IsEnabledAsync(WeChatOfficialFeatures.EnableAuthorization))
{
context.Result = new GrantValidationResult(
TokenRequestErrors.InvalidGrant,
WeChatLocalizer["OfficialAuthorizationDisabledMessage"]);
return false;
}
return true;
}
protected override async Task<WeChatOpenId> FindOpenIdAsync(string code)
{
var options = await WeChatOfficialOptionsFactory.CreateAsync();
return await WeChatOpenIdFinder.FindAsync(code, options.AppId, options.AppSecret);
}
}
}

71
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/Official/WeChatOfficialOAuthConsts.cs

@ -1,71 +0,0 @@
using LINGYUN.Abp.WeChat;
using LINGYUN.Abp.WeChat.Official;
namespace LINGYUN.Abp.IdentityServer.WeChat.Official
{
/// <summary>
/// 与微信公众号认证相关的静态(可变)常量
/// </summary>
public static class WeChatOfficialOAuthConsts
{
/// <summary>
/// 微信个人信息标识
/// </summary>
public static string ProfileKey { get; set; } = "wechat.profile";
/// <summary>
/// 微信提供者标识
/// </summary>
public static string ProviderKey => AbpWeChatOfficialConsts.ProviderName;
/// <summary>
/// 微信提供者显示名称
/// </summary>
public static string DisplayName => AbpWeChatGlobalConsts.DisplayName;
/// <summary>
/// 回调地址
/// </summary>
public static string CallbackPath { get; set; } = "/signin-wechat";
/// <summary>
/// 微信客户端外的网页登录
/// </summary>
public const string QrConnectEndpoint = "https://open.weixin.qq.com/connect/qrconnect";
/// <summary>
/// 微信客户端内的网页登录
/// </summary>
public const string AuthorizationEndpoint = "https://open.weixin.qq.com/connect/oauth2/authorize";
/// <summary>
/// 用户允许授权后通过返回的code换取access_token地址
/// </summary>
public const string TokenEndpoint = "https://api.weixin.qq.com/sns/oauth2/access_token";
/// <summary>
/// 使用access_token获取用户个人信息地址
/// </summary>
public const string UserInformationEndpoint = "https://api.weixin.qq.com/sns/userinfo";
/// <summary>
/// 弹出授权页面,可通过openid拿到昵称、性别、所在地。
/// 并且, 即使在未关注的情况下,只要用户授权,也能获取其信息
/// <br />
/// <br />
/// 详询: <see cref="https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html"/>
/// </summary>
/// <remarks>
/// 以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。
/// 但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息
/// </remarks>
public const string UserInfoScope = "snsapi_userinfo";
/// <summary>
/// 不弹出授权页面,直接跳转,只能获取用户openid
/// <br />
/// <br />
/// 详询: <see cref="https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html"/>
/// </summary>
/// <remarks>
/// 以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的。
/// 用户感知的就是直接进入了回调页(往往是业务页面)
/// </remarks>
public const string LoginScope = "snsapi_login";
}
}

77
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/Official/WeChatOfficialSignatureMiddleware.cs

@ -1,77 +0,0 @@
using LINGYUN.Abp.WeChat.Official;
using Microsoft.AspNetCore.Http;
using System;
using System.Collections;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.IdentityServer.WeChat.Official
{
public class WeChatOfficialSignatureMiddleware : IMiddleware, ITransientDependency
{
protected AbpWeChatOfficialOptionsFactory WeChatOfficialOptionsFactory { get; }
public WeChatOfficialSignatureMiddleware(
AbpWeChatOfficialOptionsFactory weChatOfficialOptionsFactory)
{
WeChatOfficialOptionsFactory = weChatOfficialOptionsFactory;
}
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
if (context.Request.Path.HasValue)
{
var options = await WeChatOfficialOptionsFactory.CreateAsync();
var requestPath = context.Request.Path.Value;
// 访问地址是否与定义的地址匹配
if (requestPath.Equals(options.Url))
{
var timestamp = context.Request.Query["timestamp"];
var nonce = context.Request.Query["nonce"];
var signature = context.Request.Query["signature"];
var echostr = context.Request.Query["echostr"];
// 验证消息合法性
var check = CheckWeChatSignature(options.Token, timestamp, nonce, signature);
if (check)
{
// 验证通过需要把微信服务器传递的字符原封不动传回
await context.Response.WriteAsync(echostr);
return;
}
// 微信消息验证不通过
throw new AbpException("Invalid wechat signature");
}
}
// 不属于微信的消息进入下一个中间件
await next(context);
}
protected bool CheckWeChatSignature(string token, string timestamp, string nonce, string signature)
{
var al = new ArrayList
{
token,
timestamp,
nonce
};
// step1 排序
al.Sort();
string signatureStr = string.Empty;
// step2 拼接
for (int i = 0; i < al.Count; i++)
{
signatureStr += al[i];
}
// step3 SHA1加密
byte[] bytes_out = signatureStr.Sha1();
string result = BitConverter.ToString(bytes_out).Replace("-", "");
// step4 比对
if (result.Equals(signature, StringComparison.CurrentCultureIgnoreCase))
{
return true;
}
return false;
}
}
}

242
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/WeChatGrantValidator.cs

@ -1,242 +0,0 @@
using IdentityModel;
using IdentityServer4.Events;
using IdentityServer4.Models;
using IdentityServer4.Services;
using IdentityServer4.Validation;
using LINGYUN.Abp.WeChat;
using LINGYUN.Abp.WeChat.Localization;
using LINGYUN.Abp.WeChat.OpenId;
using LINGYUN.Abp.WeChat.Security.Claims;
using LINGYUN.Abp.WeChat.Settings;
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.DependencyInjection;
using Volo.Abp.Guids;
using Volo.Abp.Identity;
using Volo.Abp.IdentityServer;
using Volo.Abp.IdentityServer.Localization;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Security.Claims;
using Volo.Abp.Settings;
using Volo.Abp.Uow;
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 LoginProvider { get; }
public abstract string AuthenticationMethod { get; }
public ILogger Logger { protected get; set; }
public IAbpLazyServiceProvider ServiceProvider { protected get; set; }
protected IEventService EventService { get; }
protected IWeChatOpenIdFinder WeChatOpenIdFinder { get; }
protected IIdentityUserRepository UserRepository { get; }
protected IdentitySecurityLogManager IdentitySecurityLogManager { get; }
protected UserManager<IdentityUser> UserManager { get; }
protected IStringLocalizer<WeChatResource> WeChatLocalizer { get; }
protected IStringLocalizer<IdentityResource> IdentityLocalizer { get; }
protected IStringLocalizer<AbpIdentityServerResource> IdentityServerLocalizer { get; }
public WeChatGrantValidator(
IEventService eventService,
IWeChatOpenIdFinder weChatOpenIdFinder,
UserManager<IdentityUser> userManager,
IIdentityUserRepository userRepository,
IdentitySecurityLogManager identitySecurityLogManager,
IStringLocalizer<WeChatResource> wechatLocalizer,
IStringLocalizer<IdentityResource> identityLocalizer,
IStringLocalizer<AbpIdentityServerResource> identityServerLocalizer)
{
EventService = eventService;
UserManager = userManager;
UserRepository = userRepository;
IdentitySecurityLogManager = identitySecurityLogManager;
WeChatOpenIdFinder = weChatOpenIdFinder;
WeChatLocalizer = wechatLocalizer;
IdentityLocalizer = identityLocalizer;
IdentityServerLocalizer = identityServerLocalizer;
Logger = NullLogger<WeChatGrantValidator>.Instance;
}
protected abstract Task<WeChatOpenId> FindOpenIdAsync(string code);
[UnitOfWork]
public async Task ValidateAsync(ExtensionGrantValidationContext context)
{
if (!await CheckFeatureAsync(context))
{
return;
}
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;
}
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;
}
WeChatOpenId wechatOpenId;
try
{
wechatOpenId = await FindOpenIdAsync(wechatCode);
}
catch(AbpWeChatException e)
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, e.Message);
return;
}
var currentUser = await UserManager.FindByLoginAsync(LoginProvider, wechatOpenId.OpenId);
if (currentUser == null)
{
// 检查是否允许自注册
var settingProvider = ServiceProvider.LazyGetRequiredService<ISettingProvider>();
// TODO 检查启用用户注册是否有必要引用账户模块
if (!await settingProvider.IsTrueAsync("Abp.Account.IsSelfRegistrationEnabled") ||
!await settingProvider.IsTrueAsync(WeChatSettingNames.EnabledQuickLogin))
{
Logger.LogWarning("Invalid grant type: wechat openid not register", wechatOpenId.OpenId);
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, IdentityServerLocalizer["InvalidGrant:WeChatNotRegister"]);
return;
}
var guiGenerator = ServiceProvider.LazyGetRequiredService<IGuidGenerator>();
var currentTenant = ServiceProvider.LazyGetRequiredService<ICurrentTenant>();
var userName = "wxid-" + wechatOpenId.OpenId.ToMd5().ToLower();
var userEmail = $"{userName}@{currentTenant.Name ?? "default"}.io";
currentUser = new IdentityUser(guiGenerator.Create(), userName, userEmail, currentTenant.Id);
(await UserManager.CreateAsync(currentUser)).CheckErrors();
(await UserManager.AddLoginAsync(
currentUser,
new UserLoginInfo(
LoginProvider,
wechatOpenId.OpenId,
AbpWeChatGlobalConsts.DisplayName))).CheckErrors();
}
// 检查是否已锁定
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"]);
await SaveSecurityLogAsync(context, currentUser, wechatOpenId, IdentityServerSecurityLogActionConsts.LoginLockedout);
return;
}
await EventService.RaiseAsync(new UserLoginSuccessEvent(currentUser.UserName, wechatOpenId.OpenId, null));
// 登录之后需要更新安全令牌
(await UserManager.UpdateSecurityStampAsync(currentUser)).CheckErrors();
await SetSuccessResultAsync(context, currentUser, wechatOpenId);
}
protected virtual Task<bool> CheckFeatureAsync(ExtensionGrantValidationContext context)
{
return Task.FromResult(true);
}
protected async virtual Task SetSuccessResultAsync(ExtensionGrantValidationContext context, IdentityUser user, WeChatOpenId wechatOpenId)
{
var sub = await UserManager.GetUserIdAsync(user);
Logger.LogInformation("Credentials validated for username: {username}", user.UserName);
var additionalClaims = new List<Claim>();
await AddCustomClaimsAsync(additionalClaims, user, wechatOpenId, context);
context.Result = new GrantValidationResult(
sub,
AuthenticationMethod,
additionalClaims.ToArray()
);
await SaveSecurityLogAsync(
context,
user,
wechatOpenId,
IdentityServerSecurityLogActionConsts.LoginSucceeded);
}
protected async virtual Task SaveSecurityLogAsync(
ExtensionGrantValidationContext context,
IdentityUser user,
WeChatOpenId wechatOpenId,
string action)
{
var logContext = new IdentitySecurityLogContext
{
Identity = IdentityServerSecurityLogIdentityConsts.IdentityServer,
Action = action,
UserName = user.UserName,
ClientId = await FindClientIdAsync(context)
};
logContext.WithProperty("GrantType", GrantType);
logContext.WithProperty("Provider", LoginProvider);
logContext.WithProperty("Method", AuthenticationMethod);
await IdentitySecurityLogManager.SaveAsync(logContext);
}
protected virtual Task<string> FindClientIdAsync(ExtensionGrantValidationContext context)
{
return Task.FromResult(context.Request?.Client?.ClientId);
}
protected virtual Task AddCustomClaimsAsync(
List<Claim> customClaims,
IdentityUser user,
WeChatOpenId wechatOpenId,
ExtensionGrantValidationContext context)
{
if (user.TenantId.HasValue)
{
customClaims.Add(
new Claim(
AbpClaimTypes.TenantId,
user.TenantId?.ToString()
)
);
}
customClaims.Add(
new Claim(
AbpWeChatClaimTypes.OpenId,
wechatOpenId.OpenId));
if (!wechatOpenId.UnionId.IsNullOrWhiteSpace())
{
customClaims.Add(
new Claim(
AbpWeChatClaimTypes.UnionId,
wechatOpenId.UnionId));
}
return Task.CompletedTask;
}
}
}

86
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/WeChatResourceDataSeeder.cs

@ -1,86 +0,0 @@
using LINGYUN.Abp.IdentityServer.WeChat.Official;
using LINGYUN.Abp.WeChat.Security.Claims;
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 async virtual 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(
WeChatOfficialOAuthConsts.ProfileKey,
WeChatOfficialOAuthConsts.DisplayName,
wechatClaimTypes);
foreach (var claimType in wechatClaimTypes)
{
await AddClaimTypeIfNotExistsAsync(claimType);
}
await AddIdentityResourceIfNotExistsAsync(wechatResource);
}
protected async virtual Task AddIdentityResourceIfNotExistsAsync(IdentityServer4.Models.IdentityResource resource)
{
if (await IdentityResourceRepository.CheckNameExistAsync(resource.Name))
{
return;
}
await IdentityResourceRepository.InsertAsync(
new IdentityResource(
GuidGenerator.Create(),
resource
)
);
}
protected async virtual Task AddClaimTypeIfNotExistsAsync(string claimType)
{
if (await ClaimTypeRepository.AnyAsync(claimType))
{
return;
}
await ClaimTypeRepository.InsertAsync(
new IdentityClaimType(
GuidGenerator.Create(),
claimType,
isStatic: true
)
);
}
}
}

336
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/Microsoft/AspNetCore/Authentication/WeChat/Official/WeChatOfficialOAuthHandler.cs

@ -1,336 +0,0 @@
using LINGYUN.Abp.IdentityServer.WeChat.Official;
using LINGYUN.Abp.WeChat.Official;
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.Official
{
/// <summary>
/// 网页授权只有公众平台的实现
/// </summary>
public class WeChatOfficialOAuthHandler : OAuthHandler<WeChatOfficialOAuthOptions>
{
protected IDistributedCache<WeChatOfficialStateCacheItem> Cache { get; }
protected AbpWeChatOfficialOptionsFactory WeChatOfficialOptionsFactory { get; }
public WeChatOfficialOAuthHandler(
IDistributedCache<WeChatOfficialStateCacheItem> cache,
IOptionsMonitor<WeChatOfficialOAuthOptions> options,
AbpWeChatOfficialOptionsFactory weChatOfficialOptionsFactory,
ILoggerFactory logger,
UrlEncoder encoder,
ISystemClock clock)
: base(options, logger, encoder, clock)
{
Cache = cache;
WeChatOfficialOptionsFactory = weChatOfficialOptionsFactory;
}
protected override async Task InitializeHandlerAsync()
{
var weChatOfficialOptions = await WeChatOfficialOptionsFactory.CreateAsync();
// 用配置项重写
Options.ClientId = weChatOfficialOptions.AppId;
Options.ClientSecret = weChatOfficialOptions.AppSecret;
await base.InitializeHandlerAsync();
}
protected override async Task<AuthenticationTicket> CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens)
{
var address = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, new Dictionary<string, string>
{
["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 = WeChatOfficialStateCacheItem.CalculateCacheKey(state.ToString().ToMd5(), null);
await Cache.RemoveAsync(stateCacheKey, token: Context.RequestAborted);
return new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name);
}
/// <summary>
/// code换取access_token
/// </summary>
protected override async Task<OAuthTokenResponse> ExchangeCodeAsync(OAuthCodeExchangeContext context)
{
var address = QueryHelpers.AddQueryString(Options.TokenEndpoint, new Dictionary<string, string>()
{
["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之后再进行缓存
// 注: 默认的State对于微信来说太长(微信只支持128位长度的State),因此巧妙的利用CorrelationId的MD5值来替代State
// MD5转换防止直接通过CorrelationId干些别的事情...
var state = properties.Items[".xsrf"];
var stateToken = Options.StateDataFormat.Protect(properties);
var stateCacheKey = WeChatOfficialStateCacheItem.CalculateCacheKey(state.ToMd5(), null);
await Cache
.SetAsync(
stateCacheKey,
new WeChatOfficialStateCacheItem(stateToken),
new DistributedCacheEntryOptions
{
AbsoluteExpiration = Clock.UtcNow.AddMinutes(2) // TODO: 设定2分钟过期?
},
token: Context.RequestAborted);
}
/// <summary>
/// 构建用户授权地址
/// </summary>
protected override string BuildChallengeUrl(AuthenticationProperties properties, string redirectUri)
{
var state = properties.Items[".xsrf"];
var isWeChatBrewserRequest = IsWeChatBrowser();
var scope = isWeChatBrewserRequest
? WeChatOfficialOAuthConsts.UserInfoScope
: FormatScope();
var endPoint = isWeChatBrewserRequest
? Options.AuthorizationEndpoint
: WeChatOfficialOAuthConsts.QrConnectEndpoint;
var challengeUrl = QueryHelpers.AddQueryString(endPoint, new Dictionary<string, string>
{
["appid"] = Options.ClientId,
["redirect_uri"] = redirectUri,
["response_type"] = "code"
});
challengeUrl += $"&scope={scope}&state={state.ToMd5()}";
return challengeUrl;
}
protected override async Task<HandleRequestResult> HandleRemoteAuthenticateAsync()
{
var query = Request.Query;
// TODO: 此处借用唯一的 CorrelationId, 将 properties生成的State缓存取出,进行解密
var state = query["state"];
var stateCacheKey = WeChatOfficialStateCacheItem.CalculateCacheKey(state.ToString().ToMd5(), 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<AuthenticationToken>();
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);
}
}
}

47
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/Microsoft/AspNetCore/Authentication/WeChat/Official/WeChatOfficialOAuthOptions.cs

@ -1,47 +0,0 @@
using LINGYUN.Abp.IdentityServer.WeChat.Official;
using LINGYUN.Abp.WeChat.Security.Claims;
using Microsoft.AspNetCore.Authentication.OAuth;
using Microsoft.AspNetCore.Http;
using System.Security.Claims;
using System.Text.Json;
namespace Microsoft.AspNetCore.Authentication.WeChat.Official
{
public class WeChatOfficialOAuthOptions : OAuthOptions
{
public WeChatOfficialOAuthOptions()
{
// 用于防止初始化错误,会在OAuthHandler.InitializeHandlerAsync中进行重写
ClientId = "WeChatOfficial";
ClientSecret = "WeChatOfficial";
ClaimsIssuer = WeChatOfficialOAuthConsts.ProviderKey;
CallbackPath = new PathString(WeChatOfficialOAuthConsts.CallbackPath);
AuthorizationEndpoint = WeChatOfficialOAuthConsts.AuthorizationEndpoint;
TokenEndpoint = WeChatOfficialOAuthConsts.TokenEndpoint;
UserInformationEndpoint = WeChatOfficialOAuthConsts.UserInformationEndpoint;
Scope.Add(WeChatOfficialOAuthConsts.LoginScope);
Scope.Add(WeChatOfficialOAuthConsts.UserInfoScope);
// 这个原始的属性一定要写进去,框架与UserLogin.ProviderKey进行关联判断是否绑定微信
ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "openid");
ClaimActions.MapJsonKey(ClaimTypes.Name, "nickname");
// 把自定义的身份标识写进令牌
ClaimActions.MapJsonKey(AbpWeChatClaimTypes.OpenId, "openid");
ClaimActions.MapJsonKey(AbpWeChatClaimTypes.UnionId, "unionid");// 公众号如果与小程序关联,这个可以用上
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"));
});
}
}
}

18
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/Microsoft/AspNetCore/Authentication/WeChat/Official/WeChatOfficialStateCacheItem.cs

@ -1,18 +0,0 @@
namespace Microsoft.AspNetCore.Authentication.WeChat.Official
{
public class WeChatOfficialStateCacheItem
{
public string State { get; set; }
public WeChatOfficialStateCacheItem() { }
public WeChatOfficialStateCacheItem(string state)
{
State = state;
}
public static string CalculateCacheKey(string correlationId, string purpose)
{
return $"ci:{correlationId};p:{purpose ?? "null"}";
}
}
}

65
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/Microsoft/AspNetCore/Authentication/WeChatAuthenticationExtensions.cs

@ -1,65 +0,0 @@
using LINGYUN.Abp.IdentityServer.WeChat.Official;
using LINGYUN.Abp.WeChat;
using Microsoft.AspNetCore.Authentication.WeChat.Official;
using Microsoft.Extensions.DependencyInjection;
using System;
namespace Microsoft.AspNetCore.Authentication
{
public static class WeChatAuthenticationExtensions
{
/// <summary>
/// </summary>
public static AuthenticationBuilder AddWeChat(
this AuthenticationBuilder builder)
{
return builder
.AddWeChat(
AbpWeChatGlobalConsts.AuthenticationScheme,
AbpWeChatGlobalConsts.DisplayName,
options => { });
}
/// <summary>
/// </summary>
public static AuthenticationBuilder AddWeChat(
this AuthenticationBuilder builder,
Action<WeChatOfficialOAuthOptions> configureOptions)
{
return builder
.AddWeChat(
AbpWeChatGlobalConsts.AuthenticationScheme,
AbpWeChatGlobalConsts.DisplayName,
configureOptions);
}
/// <summary>
/// </summary>
public static AuthenticationBuilder AddWeChat(
this AuthenticationBuilder builder,
string authenticationScheme,
Action<WeChatOfficialOAuthOptions> configureOptions)
{
return builder
.AddWeChat(
authenticationScheme,
WeChatOfficialOAuthConsts.DisplayName,
configureOptions);
}
/// <summary>
/// </summary>
public static AuthenticationBuilder AddWeChat(
this AuthenticationBuilder builder,
string authenticationScheme,
string displayName,
Action<WeChatOfficialOAuthOptions> configureOptions)
{
return builder
.AddOAuth<WeChatOfficialOAuthOptions, WeChatOfficialOAuthHandler>(
authenticationScheme,
displayName,
configureOptions);
}
}
}

22
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/Microsoft/AspNetCore/Builder/IdentityServerApplicationBuilderExtensions.cs

@ -1,22 +0,0 @@
using LINGYUN.Abp.IdentityServer.WeChat.Official;
namespace Microsoft.AspNetCore.Builder
{
public static class IdentityServerApplicationBuilderExtensions
{
/// <summary>
/// 启用中间件可以处理微信服务器消息
/// 用于验证消息是否来自于微信服务器
/// </summary>
/// <param name="builder"></param>
/// <remarks>
/// 也可以用Controller的形式来实现
/// </remarks>
/// <returns></returns>
public static IApplicationBuilder UseWeChatSignature(this IApplicationBuilder builder)
{
builder.UseMiddleware<WeChatOfficialSignatureMiddleware>();
return builder;
}
}
}

16
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/System/BytesExtensions.cs

@ -1,16 +0,0 @@
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;
}
}
}
}

17
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/System/StringExtensions.cs

@ -1,17 +0,0 @@
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;
}
}
}
}

63
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/System/Text/Json/JsonElementExtensions.cs

@ -1,63 +0,0 @@
using System.Collections.Generic;
namespace System.Text.Json
{
internal static class JsonElementExtensions
{
public static IEnumerable<string> GetRootStrings(this JsonDocument json, string key)
{
return json.RootElement.GetStrings(key);
}
public static IEnumerable<string> GetStrings(this JsonElement json, string key)
{
var result = new List<string>();
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;
}
}
}
Loading…
Cancel
Save