diff --git a/aspnet-core/configuration/AuthServer.Host/appsettings.Development.json b/aspnet-core/configuration/AuthServer.Host/appsettings.Development.json new file mode 100644 index 000000000..aa82f1d34 --- /dev/null +++ b/aspnet-core/configuration/AuthServer.Host/appsettings.Development.json @@ -0,0 +1,141 @@ +{ + "App": { + "SelfUrl": "http://localhost:44385/", + "CorsOrigins": "http://localhost:4200,http://localhost:9528,http://127.0.0.1:63898" + }, + "AppSelfUrl": "http://localhost:44385/", + "ConnectionStrings": { + "Default": "Server=127.0.0.1;Database=IdentityServer;User Id=root;Password=123456", + "AbpIdentity": "Server=127.0.0.1;Database=IdentityServer;User Id=root;Password=123456", + "AbpIdentityServer": "Server=127.0.0.1;Database=IdentityServer;User Id=root;Password=123456", + "AbpTenantManagement": "Server=127.0.0.1;Database=Platform;User Id=root;Password=123456", + "AbpSettingManagement": "Server=127.0.0.1;Database=Platform;User Id=root;Password=123456", + "AbpPermissionManagement": "Server=127.0.0.1;Database=Platform;User Id=root;Password=123456", + "AbpFeatureManagement": "Server=127.0.0.1;Database=Platform;User Id=root;Password=123456" + }, + "Identity": { + "Password": { + "RequiredLength": 6, + "RequiredUniqueChars": 0, + "RequireNonAlphanumeric": false, + "RequireLowercase": false, + "RequireUppercase": false, + "RequireDigit": false + }, + "Lockout": { + "AllowedForNewUsers": false, + "LockoutDuration": 5, + "MaxFailedAccessAttempts": 5 + }, + "SignIn": { + "RequireConfirmedEmail": false, + "RequireConfirmedPhoneNumber": false + } + }, + "CAP": { + "EventBus": { + "DefaultGroup": "AuthServer", + "Version": "v1", + "FailedRetryInterval": 300, + "FailedRetryCount": 10 + }, + "RabbitMQ": { + "HostName": "127.0.0.1", + "Port": 5672, + "UserName": "admin", + "Password": "admin", + "ExchangeName": "LINGYUN.AbpApplication", + "VirtualHost": "multi.service.test" + } + }, + "RedisCache": { + "ConnectString": "127.0.0.1", + "RedisPrefix": "AuthServer" + }, + "AuthServer": { + "Authority": "http://localhost:44385/", + "ApiName": "auth-service" + }, + "WeChat": { + "Auth": { + "AppId": "微信AppId", + "AppSecret": "微信AppSecret" + }, + "Signature": { + "RequestPath": "微信开发者中心填写的验证地址", + "Token": "微信开发者中心填写的Token" + } + }, + "IdentityServer": { + "Clients": { + "AuthManagement": { + "ClientId": "auth-management", + "RootUrl": "http://localhost:44313/" + }, + "AuthVueAdmin": { + "ClientId": "vue-admin-element" + }, + "AuthApiGateway": { + "ClientId": "apigateway-host-client" + } + } + }, + "Serilog": { + "MinimumLevel": { + "Default": "Information", + "Override": { + "System": "Warning", + "Microsoft": "Warning", + "DotNetCore": "Information" + } + }, + "Enrich": [ "FromLogContext", "WithProcessId", "WithThreadId" ], + "WriteTo": [ + { + "Name": "File", + "Args": { + "path": "Logs/Debug-.log", + "restrictedToMinimumLevel": "Debug", + "rollingInterval": "Day", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" + } + }, + { + "Name": "File", + "Args": { + "path": "Logs/Info-.log", + "restrictedToMinimumLevel": "Information", + "rollingInterval": "Day", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" + } + }, + { + "Name": "File", + "Args": { + "path": "Logs/Warn-.log", + "restrictedToMinimumLevel": "Warning", + "rollingInterval": "Day", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" + } + }, + { + "Name": "File", + "Args": { + "path": "Logs/Error-.log", + "restrictedToMinimumLevel": "Error", + "rollingInterval": "Day", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" + } + }, + { + "Name": "File", + "Args": { + "path": "Logs/Fatal-.log", + "restrictedToMinimumLevel": "Fatal", + "rollingInterval": "Day", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" + } + } + ] + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatSignatureMiddleware.cs b/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatSignatureMiddleware.cs index 65a3a53aa..48c3a040d 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatSignatureMiddleware.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatSignatureMiddleware.cs @@ -23,47 +23,56 @@ namespace LINGYUN.Abp.IdentityServer if (context.Request.Path.HasValue) { var requestPath = context.Request.Path.Value; + // 访问地址是否与定义的地址匹配 if (requestPath.Equals(Options.RequestPath)) { 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("微信验证不通过"); + // 微信消息验证不通过 + throw new AbpException("Invalid wechat signature"); } } + // 不属于微信的消息进入下一个中间件 await next(context); } protected bool CheckWeChatSignature(string token, string timestamp, string nonce, string signature) { - var al = new ArrayList(); - al.Add(token); - al.Add(timestamp); - al.Add(nonce); + var al = new ArrayList + { + token, + timestamp, + nonce + }; + // step1 排序 al.Sort(); string signatureStr = string.Empty; - for(int i = 0; i < al.Count; i++) + // step2 拼接 + for (int i = 0; i < al.Count; i++) { signatureStr += al[i]; } - using (var sha1 = new SHA1CryptoServiceProvider()) + // step3 SHA1加密 + using var sha1 = new SHA1CryptoServiceProvider(); + byte[] bytes_in = Encoding.ASCII.GetBytes(signatureStr); + byte[] bytes_out = sha1.ComputeHash(bytes_in); + string result = BitConverter.ToString(bytes_out).Replace("-", ""); + // step4 比对 + if (result.Equals(signature, StringComparison.CurrentCultureIgnoreCase)) { - byte[] bytes_in = Encoding.ASCII.GetBytes(signatureStr); - byte[] bytes_out = sha1.ComputeHash(bytes_in); - string result = BitConverter.ToString(bytes_out).Replace("-", ""); - if (result.Equals(signature, StringComparison.CurrentCultureIgnoreCase)) - { - return true; - } - return false; + return true; } + return false; } } } diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatSignatureOptions.cs b/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatSignatureOptions.cs index 76a6f1c8e..7e5b82154 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatSignatureOptions.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatSignatureOptions.cs @@ -2,7 +2,15 @@ { public class WeChatSignatureOptions { + /// + /// 微信服务器请求路径 + /// 填写在微信开发者中心配置的地址 + /// public string RequestPath { get; set; } + /// + /// 微信服务器请求token + /// 填写在微信开发者中心配置的token + /// public string Token { get; set; } } } diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/Microsoft/AspNetCore/Builder/IdentityServerApplicationBuilderExtensions.cs b/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/Microsoft/AspNetCore/Builder/IdentityServerApplicationBuilderExtensions.cs index 91d411491..f8b805fbe 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/Microsoft/AspNetCore/Builder/IdentityServerApplicationBuilderExtensions.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/Microsoft/AspNetCore/Builder/IdentityServerApplicationBuilderExtensions.cs @@ -4,6 +4,15 @@ namespace Microsoft.AspNetCore.Builder { public static class IdentityServerApplicationBuilderExtensions { + /// + /// 启用中间件可以处理微信服务器消息 + /// 用于验证消息是否来自于微信服务器 + /// + /// + /// + /// 也可以用Controller的形式来实现 + /// + /// public static IApplicationBuilder UseWeChatSignature(this IApplicationBuilder builder) { builder.UseMiddleware(); diff --git a/aspnet-core/services/account/AuthServer.Host/AuthIdentityServerModule.cs b/aspnet-core/services/account/AuthServer.Host/AuthIdentityServerModule.cs index 46ff7dcb9..d8b85a023 100644 --- a/aspnet-core/services/account/AuthServer.Host/AuthIdentityServerModule.cs +++ b/aspnet-core/services/account/AuthServer.Host/AuthIdentityServerModule.cs @@ -85,6 +85,7 @@ namespace AuthServer.Host // 滑动过期30天 options.GlobalCacheEntryOptions.SlidingExpiration = TimeSpan.FromDays(30); // 绝对过期60天 + options.GlobalCacheEntryOptions.AbsoluteExpiration = DateTimeOffset.Now.AddDays(60); options.GlobalCacheEntryOptions.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(60); }); @@ -116,13 +117,14 @@ namespace AuthServer.Host context.Services.AddStackExchangeRedisCache(options => { - options.InstanceName = configuration["Redis:InstanceName"]; - options.Configuration = configuration["Redis:Configuration"]; + options.Configuration = configuration["RedisCache:ConnectString"]; + var instanceName = configuration["RedisCache:RedisPrefix"]; + options.InstanceName = instanceName.IsNullOrEmpty() ? "MessageService_Cache" : instanceName; }); if (!hostingEnvironment.IsDevelopment()) { - var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]); + var redis = ConnectionMultiplexer.Connect(configuration["RedisCache:ConnectString"]); context.Services .AddDataProtection() .PersistKeysToStackExchangeRedis(redis, "AuthServer-Protection-Keys"); @@ -160,7 +162,10 @@ namespace AuthServer.Host app.UseMultiTenancy(); app.UseIdentityServer(); app.UseAuditing(); - //app.UseWeChatSignature(); + + // 处理微信消息 + // app.UseWeChatSignature(); + SeedData(context); }