diff --git a/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/Lion.AbpPro.HttpApi.Host.csproj b/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/Lion.AbpPro.HttpApi.Host.csproj index 42785380..c00c45d7 100644 --- a/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/Lion.AbpPro.HttpApi.Host.csproj +++ b/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/Lion.AbpPro.HttpApi.Host.csproj @@ -32,8 +32,6 @@ - - diff --git a/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/Properties/launchSettings.json b/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/Properties/launchSettings.json index eef4b766..06204a73 100644 --- a/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/Properties/launchSettings.json +++ b/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/Properties/launchSettings.json @@ -5,7 +5,7 @@ "launchBrowser": true, "applicationUrl": "http://localhost:44315", "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" + "ASPNETCORE_ENVIRONMENT": "Production" } } } diff --git a/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/appsettings.json b/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/appsettings.json index aae82f39..72852d44 100644 --- a/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/appsettings.json +++ b/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/appsettings.json @@ -16,7 +16,7 @@ "CorsOrigins": "https://*.AbpPro.com,http://localhost:4200,http://localhost:3100" }, "ConnectionStrings": { - "Default": "Data Source=localhost;Database=LionAbpProDB;uid=root;pwd=123456;charset=utf8mb4;Allow User Variables=true;AllowLoadLocalInfile=true" + "Default": "Data Source=120.24.194.14;Port=3307;Database=LionAbpProDB;uid=root;pwd=1q2w3E*;charset=utf8mb4;Allow User Variables=true;AllowLoadLocalInfile=true" }, "Redis": { "Configuration": "localhost,password=mypassword,defaultdatabase=1" diff --git a/aspnet-core/services/host/Lion.AbpPro.IdentityServer/Properties/launchSettings.json b/aspnet-core/services/host/Lion.AbpPro.IdentityServer/Properties/launchSettings.json index eb7e0389..2f3f580b 100644 --- a/aspnet-core/services/host/Lion.AbpPro.IdentityServer/Properties/launchSettings.json +++ b/aspnet-core/services/host/Lion.AbpPro.IdentityServer/Properties/launchSettings.json @@ -5,7 +5,7 @@ "launchBrowser": false, "applicationUrl": "http://localhost:44354", "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" + "ASPNETCORE_ENVIRONMENT": "Production" } } } diff --git a/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.Server/AbpProWebBlazorServerConsts.cs b/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.Server/AbpProWebBlazorServerConsts.cs new file mode 100644 index 00000000..d0b6488c --- /dev/null +++ b/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.Server/AbpProWebBlazorServerConsts.cs @@ -0,0 +1,40 @@ +namespace Lion.AbpPro +{ + public class AbpProWebBlazorServerConsts + { + /// + /// 跨域策略名 + /// + public const string DefaultCorsPolicyName = "Default"; + + /// + /// Cookies名称 + /// + public const string DefaultCookieName = "Lion.AbpPro.Http.Api"; + + /// + /// SwaggerUi 端点 + /// + public const string SwaggerUiEndPoint = "/swagger"; + + /// + /// Hangfire 端点 + /// + public const string HangfireDashboardEndPoint = "/hangfire"; + + /// + /// CAP 端点 + /// + public const string CapDashboardEndPoint = "/cap"; + + + public const string MoreEndPoint = "https://doc.cncore.club/"; + + + /// + /// HMiniprofiler端点 + /// + public const string MiniprofilerEndPoint = "/profiler/results-index"; + + } +} \ No newline at end of file diff --git a/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.Server/AbpProWebBlazorServerModule.cs b/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.Server/AbpProWebBlazorServerModule.cs index d5904a8d..6da54ab6 100644 --- a/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.Server/AbpProWebBlazorServerModule.cs +++ b/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.Server/AbpProWebBlazorServerModule.cs @@ -1,49 +1,376 @@ -using Lion.AbpPro.Blazor.Layout.AntDesignTheme; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Hangfire; +using Hangfire.MySql; +using Lion.AbpPro.Blazor.Layout.AntDesignTheme; +using Lion.AbpPro.CAP; +using Lion.AbpPro.ConfigurationOptions; +using Lion.AbpPro.EntityFrameworkCore; +using Lion.AbpPro.Extensions; +using Lion.AbpPro.MultiTenancy; +using Lion.AbpPro.Swaggers; using Lion.AbpPro.Web.Blazor.Server.Data; +using LionAbpPro.Extensions.Filters; +using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using Microsoft.IdentityModel.Tokens; +using Microsoft.OpenApi.Models; +using Savorboard.CAP.InMemoryMessageQueue; +using Serilog; +using StackExchange.Redis; +using Swashbuckle.AspNetCore.SwaggerUI; using Volo.Abp; +using Volo.Abp.Account.Web; +using Volo.Abp.AspNetCore.Authentication.JwtBearer; +using Volo.Abp.AspNetCore.Components.Server.Theming; +using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.AspNetCore.Serilog; using Volo.Abp.Autofac; +using Volo.Abp.BackgroundJobs; +using Volo.Abp.BackgroundJobs.Hangfire; +using Volo.Abp.Caching; +using Volo.Abp.Caching.StackExchangeRedis; using Volo.Abp.Modularity; namespace Lion.AbpPro.Web.Blazor.Server { [DependsOn(typeof(AbpAutofacModule), typeof(AbpAspNetCoreSerilogModule), - typeof(AbpProBlazorLayoutAntDesignThemeModule))] + typeof(AbpProBlazorLayoutAntDesignThemeModule), + typeof(AbpProApplicationModule), + typeof(AbpProEntityFrameworkCoreModule), + typeof(AbpAccountWebModule), + typeof(AbpAspNetCoreSerilogModule), + typeof(AbpAutofacModule), + typeof(AbpBackgroundJobsHangfireModule), + typeof(AbpProAbpCapModule), + typeof(SharedHostingMicroserviceModule), + typeof(AbpCachingStackExchangeRedisModule), + typeof(AbpAspNetCoreAuthenticationJwtBearerModule), + typeof(AbpAspNetCoreComponentsServerThemingModule))] public class AbpProWebBlazorServerModule:AbpModule { - public override void ConfigureServices(ServiceConfigurationContext context) + public override void ConfigureServices(ServiceConfigurationContext context) { - context.Services.AddRazorPages(); - context.Services.AddServerSideBlazor(); - context.Services.AddSingleton(); + var configuration = context.Services.GetConfiguration(); + ConfigureCache(context); + ConfigureSwaggerServices(context, configuration); + ConfigureOptions(context); + ConfigureJwtAuthentication(context, configuration); + ConfigureHangfireMysql(context); + ConfigurationCap(context); + ConfigurationStsHttpClient(context); + ConfigurationMiniProfiler(context); } public override void OnApplicationInitialization(ApplicationInitializationContext context) { - var env = context.GetEnvironment(); var app = context.GetApplicationBuilder(); - if (env.IsDevelopment()) + var configuration = context.GetConfiguration(); + app.UseAbpRequestLocalization(); + app.UseCorrelationId(); + app.UseStaticFiles(); + app.UseMiniProfiler(); + app.UseRouting(); + app.UseCors(AbpProWebBlazorServerConsts.DefaultCorsPolicyName); + app.UseAuthentication(); + + if (MultiTenancyConsts.IsEnabled) { - app.UseDeveloperExceptionPage(); + app.UseMultiTenancy(); } - else + + app.UseAuthorization(); + app.UseSwagger(); + app.UseAbpSwaggerUI(options => + { + options.SwaggerEndpoint("/swagger/AbpPro/swagger.json", "AbpPro API"); + options.DocExpansion(DocExpansion.None); + options.DefaultModelsExpandDepth(-1); + }); + + app.UseAuditing(); + app.UseAbpSerilogEnrichers(); + app.UseSerilogRequestLogging(opts => + { + opts.EnrichDiagnosticContext = SerilogToEsExtensions.EnrichFromRequest; + }); + app.UseUnitOfWork(); + app.UseConfiguredEndpoints(endpoints => { endpoints.MapHealthChecks("/health"); }); + app.UseHangfireDashboard("/hangfire", new DashboardOptions() + { + Authorization = new[] { new CustomHangfireAuthorizeFilter() }, + IgnoreAntiforgeryToken = true + }); + + if (configuration.GetValue("Consul:Enabled", false)) { - app.UseExceptionHandler("/Error"); + app.UseConsul(); } + } - app.UseStaticFiles(); - app.UseRouting(); + private void ConfigureHangfireMysql(ServiceConfigurationContext context) + { + Configure(options => + { + options.IsJobExecutionEnabled = true; + }); + context.Services.AddHangfire(config => + { + config.UseStorage(new MySqlStorage( + context.Services.GetConfiguration().GetConnectionString("Default"), + new MySqlStorageOptions() + { + //CommandBatchMaxTimeout = TimeSpan.FromMinutes(5), + //SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5), + //QueuePollInterval = TimeSpan.Zero, + //UseRecommendedIsolationLevel = true, + //DisableGlobalLocks = true + })); + }); + } + + /// + /// 配置MiniProfiler + /// + /// + private void ConfigurationMiniProfiler(ServiceConfigurationContext context) + { + + context.Services.AddMiniProfiler(options => options.RouteBasePath = "/profiler") + .AddEntityFramework(); + } + + /// + /// 配置JWT + /// + /// + /// + private void ConfigureJwtAuthentication(ServiceConfigurationContext context, + IConfiguration configuration) + { + context.Services.AddAuthentication(options => + { + options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + }) + .AddJwtBearer(options => + { + options.TokenValidationParameters = + new Microsoft.IdentityModel.Tokens.TokenValidationParameters() + { + // 是否开启签名认证 + ValidateIssuerSigningKey = true, + ValidateIssuer = true, + ValidateAudience = true, + ValidateLifetime = true, + //ClockSkew = TimeSpan.Zero, + ValidIssuer = configuration["Jwt:Issuer"], + ValidAudience = configuration["Jwt:Audience"], + IssuerSigningKey = + new SymmetricSecurityKey( + Encoding.ASCII.GetBytes(configuration["Jwt:SecurityKey"])) + }; + + options.Events = new JwtBearerEvents + { + OnMessageReceived = currentContext => + { + var path = currentContext.HttpContext.Request.Path; + if (path.StartsWithSegments("/login")) + { + return Task.CompletedTask; + } + + var accessToken = + currentContext.Request.Query["access_token"].FirstOrDefault() ?? + currentContext.Request.Cookies[ + AbpProWebBlazorServerConsts.DefaultCookieName]; + + if (accessToken.IsNullOrWhiteSpace()) + { + return Task.CompletedTask; + } + + if (path.StartsWithSegments("/signalr")) + { + currentContext.Token = accessToken; + } + + currentContext.Request.Headers.Remove("Authorization"); + currentContext.Request.Headers.Add("Authorization", + $"Bearer {accessToken}"); - app.UseEndpoints(endpoints => + // 如果请求来自hangfire 或者cap + if (path.ToString().StartsWith("/hangfire") || + path.ToString().StartsWith("/cap")) + { + // currentContext.HttpContext.Response.Headers.Remove( + // "X-Frame-Options"); + currentContext.Token = accessToken; + } + + + return Task.CompletedTask; + } + }; + }); + } + + /// + /// 配置options + /// + /// + private void ConfigureOptions(ServiceConfigurationContext context) + { + context.Services.Configure(context.Services.GetConfiguration() + .GetSection("Jwt")); + } + + /// + /// Redis缓存 + /// + private void ConfigureCache(ServiceConfigurationContext context) + { + Configure( + options => { options.KeyPrefix = "AbpPro:"; }); + var configuration = context.Services.GetConfiguration(); + var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]); + context.Services + .AddDataProtection() + .PersistKeysToStackExchangeRedis(redis, "AbpPro-Protection-Keys"); + } + + + private void ConfigurationStsHttpClient(ServiceConfigurationContext context) + { + context.Services.AddHttpClient(context.Services.GetConfiguration().GetSection("HttpClient:Sts:Name").Value, + options => + { + options.BaseAddress = + new Uri(context.Services.GetConfiguration().GetSection("HttpClient:Sts:Url") + .Value); + }); + } + + private void ConfigureConventionalControllers() + { + Configure(options => { - endpoints.MapBlazorHub(); - endpoints.MapFallbackToPage("/_Host"); + options.ConventionalControllers.Create(typeof(AbpProApplicationModule) + .Assembly); }); } + + private static void ConfigureSwaggerServices(ServiceConfigurationContext context, + IConfiguration configuration) + { + context.Services.AddSwaggerGen( + options => + { + options.SwaggerDoc("AbpPro", + new OpenApiInfo { Title = "LionAbpPro API", Version = "v1" }); + options.DocInclusionPredicate((docName, description) => true); + //TODO + // options.EnableAnnotations(); // 启用注解 + options.DocumentFilter(); + options.SchemaFilter(); + // 加载所有xml注释,这里会导致swagger加载有点缓慢 + var xmls = Directory.GetFiles(AppContext.BaseDirectory, "*.xml"); + foreach (var xml in xmls) + { + options.IncludeXmlComments(xml, true); + } + + options.AddSecurityDefinition(JwtBearerDefaults.AuthenticationScheme, + new OpenApiSecurityScheme() + { + Description = "直接在下框输入JWT生成的Token", + Name = "Authorization", + In = ParameterLocation.Header, + Type = SecuritySchemeType.Http, + Scheme = JwtBearerDefaults.AuthenticationScheme, + BearerFormat = "JWT" + + }); + options.AddSecurityRequirement(new OpenApiSecurityRequirement + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference + { + Type = ReferenceType.SecurityScheme, Id = "Bearer" + } + }, + new List() + } + }); + + options.AddSecurityDefinition("ApiKey", new OpenApiSecurityScheme() + { + Type = SecuritySchemeType.ApiKey, + In = ParameterLocation.Header, + Name = "Accept-Language", + Description = "多语言设置,系统预设语言有zh-Hans、en,默认为zh-Hans" + }); + + options.AddSecurityRequirement(new OpenApiSecurityRequirement + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference + { Type = ReferenceType.SecurityScheme, Id = "ApiKey" } + }, + new string[] { } + } + }); + }); + } + + + private void ConfigurationCap(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + var enabled = configuration.GetValue("Cap:Enabled", false); + if (enabled) + { + context.AddAbpCap(capOptions => + { + capOptions.UseEntityFramework(); + capOptions.UseRabbitMQ(option => + { + option.HostName = configuration.GetValue("Cap:RabbitMq:HostName"); + option.UserName = configuration.GetValue("Cap:RabbitMq:UserName"); + option.Password = configuration.GetValue("Cap:RabbitMq:Password"); + }); + + var hostingEnvironment = context.Services.GetHostingEnvironment(); + bool auth = !hostingEnvironment.IsDevelopment(); + capOptions.UseDashboard(options => { options.UseAuth = auth; }); + }); + } + else + { + context.AddAbpCap(capOptions => + { + capOptions.UseInMemoryStorage(); + capOptions.UseInMemoryMessageQueue(); + var hostingEnvironment = context.Services.GetHostingEnvironment(); + bool auth = !hostingEnvironment.IsDevelopment(); + capOptions.UseDashboard(options => { options.UseAuth = auth; }); + }); + } + } } } diff --git a/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.Server/Extensions/Filters/CustomHangfireAuthorizeFilter.cs b/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.Server/Extensions/Filters/CustomHangfireAuthorizeFilter.cs new file mode 100644 index 00000000..b4ac1b1d --- /dev/null +++ b/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.Server/Extensions/Filters/CustomHangfireAuthorizeFilter.cs @@ -0,0 +1,15 @@ +using Hangfire.Dashboard; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Users; + +namespace LionAbpPro.Extensions.Filters +{ + public class CustomHangfireAuthorizeFilter : IDashboardAuthorizationFilter + { + public bool Authorize(DashboardContext context) + { + var _currentUser = context.GetHttpContext().RequestServices.GetRequiredService(); + return _currentUser.IsAuthenticated; + } + } +} diff --git a/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.Server/Extensions/RecurringJobsExtensions.cs b/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.Server/Extensions/RecurringJobsExtensions.cs new file mode 100644 index 00000000..d55e94f4 --- /dev/null +++ b/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.Server/Extensions/RecurringJobsExtensions.cs @@ -0,0 +1,16 @@ +// using Hangfire; +// using Microsoft.Extensions.DependencyInjection; +// using System; +// using LionAbpPro.Jobs; +// +// namespace LionAbpPro.Extensions +// { +// public static class RecurringJobsExtensions +// { +// public static void CreateRecurringJob(this IServiceProvider service) +// { +// var job = service.GetService(); +// RecurringJob.AddOrUpdate("测试Job", () => job.ExecuteAsync(), CronTypeHelper.Minute(1)); +// } +// } +// } diff --git a/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.Server/Extensions/SerilogToEsExtensions.cs b/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.Server/Extensions/SerilogToEsExtensions.cs new file mode 100644 index 00000000..eeb1fd40 --- /dev/null +++ b/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.Server/Extensions/SerilogToEsExtensions.cs @@ -0,0 +1,141 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Configuration; +using Serilog; +using System; +using System.IO; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Extensions.Hosting; +using Serilog.Exceptions; +using Serilog.Exceptions.Core; +using Serilog.Sinks.Elasticsearch; + +namespace Lion.AbpPro.Extensions +{ + public static class SerilogToEsExtensions + { + public static void SetSerilogConfiguration(LoggerConfiguration loggerConfiguration, IConfiguration configuration, + IHostEnvironment hostingEnvironment) + { + // 默认读取 configuration 中 "Serilog" 节点下的配置 + loggerConfiguration.ReadFrom.Configuration(configuration) + .Enrich.WithExceptionDetails() + .Enrich.WithExceptionDetails(new DestructuringOptionsBuilder() + .WithDefaultDestructurers() + ) + .Enrich.FromLogContext() + .WriteTo.Console(); + + if (hostingEnvironment.IsDevelopment()) + { + loggerConfiguration.WriteTo.File("logs/logs.txt", rollingInterval: RollingInterval.Day); + } + loggerConfiguration.WriteTo.File("logs/logs.txt", rollingInterval: RollingInterval.Day); + var writeToElasticSearch = configuration.GetValue("ElasticSearch:Enabled", false); + + + // LogToElasticSearch:Enabled = true 才输出至ES + if (!writeToElasticSearch) + return; + + var applicationName = "Lion.AbpPro.HttpApi.Host"; + + var esUrl = configuration["ElasticSearch:Url"]; + // 需要设置ES URL + if (string.IsNullOrEmpty(esUrl)) + return; + + + var indexFormat = configuration["ElasticSearch:IndexFormat"]; + + // 需要设置ES URL + if (string.IsNullOrEmpty(indexFormat)) + return; + + var esUserName = configuration["ElasticSearch:UserName"]; + var esPassword = configuration["ElasticSearch:Password"]; + + loggerConfiguration.Enrich.FromLogContext().Enrich.WithExceptionDetails().WriteTo + .Elasticsearch(BuildElasticSearchSinkOptions(esUrl, indexFormat, esUserName, esPassword)); + loggerConfiguration.Enrich.WithProperty("Application", applicationName); + } + + // 创建Es连接 + private static ElasticsearchSinkOptions BuildElasticSearchSinkOptions( + string url, + string indexFormat, + string userName, + string password) + { + if (string.IsNullOrEmpty(userName)) + { + return new ElasticsearchSinkOptions(new Uri(url)) + { + AutoRegisterTemplate = true, + AutoRegisterTemplateVersion = AutoRegisterTemplateVersion.ESv7, + IndexFormat = indexFormat + }; + } + + return new ElasticsearchSinkOptions(new Uri(url)) + { + AutoRegisterTemplate = true, + AutoRegisterTemplateVersion = AutoRegisterTemplateVersion.ESv7, + IndexFormat = indexFormat, + ModifyConnectionSettings = x => x.BasicAuthentication(userName, password) + }; + } + + public static void EnrichFromRequest(IDiagnosticContext diagnosticContext, HttpContext httpContext) + { + var request = httpContext.Request; + + // 为每个请求都设置通用的属性 + diagnosticContext.Set("Host", request.Host); + diagnosticContext.Set("Protocol", request.Protocol); + diagnosticContext.Set("Scheme", request.Scheme); + diagnosticContext.Set("RemoteIpAddress", httpContext.Connection.RemoteIpAddress); + // 如果要记录 Request Body 或 Response Body + // 参考 https://stackoverflow.com/questions/60076922/serilog-logging-web-api-methods-adding-context-properties-inside-middleware + string requestBody = ReadRequestBody(httpContext.Request).Result; + if (!string.IsNullOrEmpty(requestBody)) + { + diagnosticContext.Set("RequestBody", requestBody); + } + + // string responseBody = ReadResponseBody(httpContext.Response).Result; + // if (!string.IsNullOrEmpty(responseBody)) + // { + // diagnosticContext.Set("ResponseBody", requestBody); + // } + + if (request.QueryString.HasValue) + { + diagnosticContext.Set("QueryString", request.QueryString.Value); + } + } + + private static async Task ReadRequestBody(HttpRequest request) + { + HttpRequestRewindExtensions.EnableBuffering(request); + + var body = request.Body; + var buffer = new byte[Convert.ToInt32(request.ContentLength)]; + await request.Body.ReadAsync(buffer, 0, buffer.Length); + string requestBody = Encoding.UTF8.GetString(buffer); + body.Seek(0, SeekOrigin.Begin); + request.Body = body; + + return $"{requestBody}"; + } + + private static async Task ReadResponseBody(HttpResponse response) + { + response.Body.Seek(0, SeekOrigin.Begin); + string responseBody = await new StreamReader(response.Body).ReadToEndAsync(); + response.Body.Seek(0, SeekOrigin.Begin); + + return $"{responseBody}"; + } + } +} \ No newline at end of file diff --git a/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.Server/Lion.AbpPro.Web.Blazor.Server.csproj b/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.Server/Lion.AbpPro.Web.Blazor.Server.csproj index be5635ab..d3148418 100644 --- a/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.Server/Lion.AbpPro.Web.Blazor.Server.csproj +++ b/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.Server/Lion.AbpPro.Web.Blazor.Server.csproj @@ -1,19 +1,39 @@ - + net6.0 + + + - - + + + + + + + + + + + + + + + + + + + diff --git a/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.Server/appsettings.json b/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.Server/appsettings.json index d9d9a9bf..72852d44 100644 --- a/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.Server/appsettings.json +++ b/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.Server/appsettings.json @@ -1,10 +1,60 @@ { - "Logging": { - "LogLevel": { + "Serilog": { + "MinimumLevel": { "Default": "Information", - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" + "Override": { + "Microsoft": "Information", + "Volo.Abp": "Information", + "Hangfire": "Information", + "DotNetCore.CAP": "Information", + "Serilog.AspNetCore": "Information" + } } }, - "AllowedHosts": "*" -} + "App": { + "SelfUrl": "http://localhost:44315", + "CorsOrigins": "https://*.AbpPro.com,http://localhost:4200,http://localhost:3100" + }, + "ConnectionStrings": { + "Default": "Data Source=120.24.194.14;Port=3307;Database=LionAbpProDB;uid=root;pwd=1q2w3E*;charset=utf8mb4;Allow User Variables=true;AllowLoadLocalInfile=true" + }, + "Redis": { + "Configuration": "localhost,password=mypassword,defaultdatabase=1" + }, + "Jwt": { + "Audience": "LionAbpPro", + //客户端标识 + "SecurityKey": "dzehzRz9a8asdfasfdadfasdfasdfafsdadfasbasdf=", + "Issuer": "LionAbpPro", + //签发者 + "ExpirationTime": 24 + //过期时间 hour + }, + "Cap": { + "Enabled": "false", + "RabbitMq": { + "HostName": "localhost", + "UserName": "admin", + "Password": "admin" + } + }, + "ElasticSearch": { + "Enabled": "false", + "Url": "http://es.cn", + "IndexFormat": "companyname.projectname.development.{0:yyyy.MM.dd}", + "UserName": "elastic", + "Password": "aVVhjQ95RP7nbwNy", + "SearchIndexFormat": "companyname.projectname.development*" + }, + "HttpClient": { + "Sts": { + "Name": "Sts", + "Url": "http://localhost:44354" + } + }, + "Consul": { + "Enabled": false, + "Host": "http://localhost:8500", + "Service": "Project-Service" + } +} \ No newline at end of file diff --git a/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.Server/tempkey.jwk b/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.Server/tempkey.jwk new file mode 100644 index 00000000..04bfd2cd --- /dev/null +++ b/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.Server/tempkey.jwk @@ -0,0 +1 @@ +{"AdditionalData":{},"Alg":"RS256","Crv":null,"D":"PAgZOVLyS9SDqZAG-veT2mLtljxhIWaEMGGaesaCzp_8NSQSZD-ZKJCnht8zaG3I73PQ1Q3eFff11yLL80WP2v43LE-m735Rm-hWL7QCAIuSvPLgx4hwyKDs6KTYKFhiOjtjnMJP5g22ETR9yOeEswhjDvgcBdHcau0aQyELQnk9HtkS-TlaCykWjRy_uJ_mLrp8qNdrVQ3nvO62ps_W0x4F4gv8Kwi_dzaqz2PVm6ZidJrF8fi7k1JtL1lcvL1-ESGVna7sNsnvFxxw98FsjR4RYTxAzai9rDFd4IbSf0Rak671cf8OT0-R0oN5Ntv7_jRH07_TJBtAaBieDUbt-Q","DP":"cpUOYvSsJQvTtjSI_ZL6k4K7pNQNgKNnL6BranMysv-x0NDy_74do7-sllvvsoPv1JbIWcqAUSAZpdaXKd9073-H-G8twds5yNS957FlSFaayCwHlFLUmyy27GMuyucEtzHruMH_8ZPSTVnCJJITFzXAnFPAJVfx7T2L7MxITbs","DQ":"E4agTm5ODGyARTv-X01HYRS8K47gPjplsqA7TA1RhzXy4jvjx2WiYoim6ji3bpKBshpswbQdBrMbAGeeb2C9rYTCJP9TpTC3JTlOBG2ZDFMtsPoiTA4Fq7EUxJtTOTNv9F81atNy1DpAOgdahHPNr2eov824AiXdgPDEIwO1XKc","E":"AQAB","K":null,"KeyId":"976444C5D95614D7E51B38BA04ABAD68","Kid":"976444C5D95614D7E51B38BA04ABAD68","Kty":"RSA","N":"u0IUokDRXdT1IdhhzmpI42ZgFAG_MwAwoLacKdRyZ0-yqlhbiQEdH5SUvqZ4bcYp7iu42iN4ppCndISCZrX6yq5EaULienJnNPpx5x8K_0_-7yG5Tz1XbQZhDtBFLLlu79BnnsotFna6m3V46dC-NaA0iE_e1RvIsPCjLhLwkX9voyminkH3s7cW7PeUEFbmAM2Wry1qavKKLvg49nRpqUuZREIofvwVA6OK_NDzWJjrX9FE5XHOCYgq9dNmeZ0J-C9W-tBdio4FNNrmDfw9P75H42FmXWqA5txjpEO-IfV7X5gOfrGAWtMGkb5uFsLw4MdIMLp22wDXrEdb5cgzjQ","Oth":null,"P":"8qMb3guW5dYik2t3mdxzGJo-P70vJV7iBhFx_8YCL3MXLFWPhwtV2b8BBIdoYkwrHcZarcdB2QLCx-Usy4E8KvNMcDCfWqQOsOLEBpQWaf4GKRmysiRi8h9u5BFDtFAIlneMv4UfMGEK0h4WkV5AvqcJY5XtkC8s8yZVEZh23TM","Q":"xZIxw3kA29tZRnuJtwYnOPWTUb0JpejV8maaPFazOZEE3mUu4ynZCReTBqpB-k5ZHL0ytwheVmfbxrbLWnBeyjl0jEp9UCFfNkjuo2EDClMo_jbpCzKy9JttqwasRLg6zgwqSuTBBlO7FJNeapIWf2amsWeB1SaFyFw2sXVxLD8","QI":"DQt4wr2gqoSG7WIaupeNIvbDbes4BD3Fu7iH-oWvSZEpJqpZ8hlIVOPdWv2aPN7JDSGGIQpyX_VqTSp1cF6OZFdO4b7Nbdm0iB9eeQNI0E8GLcS54HFI2mJq-6bLNdeNwSIlCZzjkl8cqmnLZd_3cSymlFrJP_zbyLSA26qVVZQ","Use":null,"X":null,"X5t":null,"X5tS256":null,"X5u":null,"Y":null,"KeySize":2048,"HasPrivateKey":true,"CryptoProviderFactory":{"CryptoProviderCache":{},"CustomCryptoProvider":null,"CacheSignatureProviders":true,"SignatureProviderObjectPoolCacheSize":64}} \ No newline at end of file diff --git a/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.WebAssembly/Lion.AbpPro.Web.Blazor.WebAssembly.csproj b/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.WebAssembly/Lion.AbpPro.Web.Blazor.WebAssembly.csproj index ffd85643..82c68bcb 100644 --- a/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.WebAssembly/Lion.AbpPro.Web.Blazor.WebAssembly.csproj +++ b/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.WebAssembly/Lion.AbpPro.Web.Blazor.WebAssembly.csproj @@ -20,6 +20,7 @@ + diff --git a/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.WebAssembly/WebBlazorWebAssemblyModule.cs b/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.WebAssembly/WebBlazorWebAssemblyModule.cs index fa88c365..1ca68838 100644 --- a/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.WebAssembly/WebBlazorWebAssemblyModule.cs +++ b/aspnet-core/services/host/Lion.AbpPro.Web.Blazor.WebAssembly/WebBlazorWebAssemblyModule.cs @@ -13,7 +13,8 @@ namespace Lion.AbpPro.Web.Blazor.WebAssembly [DependsOn( typeof(AbpAutofacWebAssemblyModule), typeof(AbpAspNetCoreComponentsWebAssemblyBasicThemeModule), - typeof(AbpProBlazorLayoutAntDesignThemeModule) + typeof(AbpProBlazorLayoutAntDesignThemeModule), + typeof(AbpProHttpApiClientModule) )] public class WebBlazorWebAssemblyModule:AbpModule { diff --git a/aspnet-core/services/src/Lion.AbpPro.Blazor.Layout.AntDesignTheme/AbpProBlazorLayoutAntDesignThemeModule.cs b/aspnet-core/services/src/Lion.AbpPro.Blazor.Layout.AntDesignTheme/AbpProBlazorLayoutAntDesignThemeModule.cs index fcfb579e..f42b768c 100644 --- a/aspnet-core/services/src/Lion.AbpPro.Blazor.Layout.AntDesignTheme/AbpProBlazorLayoutAntDesignThemeModule.cs +++ b/aspnet-core/services/src/Lion.AbpPro.Blazor.Layout.AntDesignTheme/AbpProBlazorLayoutAntDesignThemeModule.cs @@ -1,17 +1,10 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; -using Volo.Abp.AspNetCore.Components.Web.Theming.Routing; -using Volo.Abp.Autofac.WebAssembly; +using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; namespace Lion.AbpPro.Blazor.Layout.AntDesignTheme { [DependsOn( - typeof(AbpAutofacWebAssemblyModule) + typeof(AbpProApplicationContractsModule) )] public class AbpProBlazorLayoutAntDesignThemeModule : AbpModule { diff --git a/aspnet-core/services/src/Lion.AbpPro.Blazor.Layout.AntDesignTheme/Components/GlobalHeader/RightContent.razor b/aspnet-core/services/src/Lion.AbpPro.Blazor.Layout.AntDesignTheme/Components/GlobalHeader/RightContent.razor index 503de88f..d6918ecc 100644 --- a/aspnet-core/services/src/Lion.AbpPro.Blazor.Layout.AntDesignTheme/Components/GlobalHeader/RightContent.razor +++ b/aspnet-core/services/src/Lion.AbpPro.Blazor.Layout.AntDesignTheme/Components/GlobalHeader/RightContent.razor @@ -2,44 +2,44 @@ @inherits AntDomComponentBase - - - - - - - - - - - - - - - - - - - - - - - - + @* *@ + @* *@ + @* *@ + @* *@ + @* *@ + @* *@ + @* *@ + @* *@ + @* *@ + @* *@ + @* *@ + @* *@ + @* *@ + @* *@ + @* *@ + @* *@ + @* *@ + @* *@ + @* *@ + @* *@ + @* *@ + @* *@ + @* *@ + @* *@ \ No newline at end of file diff --git a/aspnet-core/services/src/Lion.AbpPro.Blazor.Layout.AntDesignTheme/Components/GlobalHeader/RightContent.razor.cs b/aspnet-core/services/src/Lion.AbpPro.Blazor.Layout.AntDesignTheme/Components/GlobalHeader/RightContent.razor.cs index 1d65edb5..ac54432c 100644 --- a/aspnet-core/services/src/Lion.AbpPro.Blazor.Layout.AntDesignTheme/Components/GlobalHeader/RightContent.razor.cs +++ b/aspnet-core/services/src/Lion.AbpPro.Blazor.Layout.AntDesignTheme/Components/GlobalHeader/RightContent.razor.cs @@ -1,7 +1,6 @@ using AntDesign; using AntDesign.ProLayout; using Blazored.LocalStorage; -using Lion.AbpPro.Users; using Microsoft.AspNetCore.Components; using System; using System.Collections.Generic; @@ -16,125 +15,125 @@ namespace Lion.AbpPro.Blazor.Layout.AntDesignTheme.Components.GlobalHeader { public partial class RightContent : ITransientDependency { - private readonly HttpClient _httpClient; - private readonly ILocalStorageService _localStorage; - private readonly MessageService _messageService; - private readonly NavigationManager _navigationManager; - private IDictionary _languageLabels = new Dictionary(); - private string[] _locales; - private IDictionary _languageIcons = new Dictionary(); - public RightContent( - HttpClient httpClient, - ILocalStorageService localStorage, - MessageService messageService, - NavigationManager navigationManager - ) - { - _httpClient = httpClient; - _localStorage = localStorage; - _messageService = messageService; - _navigationManager = navigationManager; - } - - public string FullScreenTipMsg { get; set; } = "全屏"; - - public AvatarMenuItem[] AvatarMenuItems { get; } = new AvatarMenuItem[] - { - new() { Key = "setting", IconType = "setting", Option = "个人设置"}, - new() { Key = "center", IconType = "user", Option = "锁定屏幕"}, - new() { IsDivider = true }, - new() { Key = "logout", IconType = "logout", Option = "注销"} - }; - protected override async Task OnInitializedAsync() - { - await base.OnInitializedAsync(); - - ClearClassMap(); - - _languageLabels.Add("zh-Hans", "简体中文"); - _languageLabels.Add("en", "English"); - - _languageIcons.Add("zh-Hans", "\ud83c\udde8\ud83c\uddf3"); - _languageIcons.Add("en", "\ud83c\uddfa\ud83c\uddf8"); - - _locales = new string[] { "zh-Hans", "en" }; - } - - private void ClearClassMap() - { - ClassMapper.Clear().Add("right"); - } - - public async Task HandleClear(string key) - { - switch (key) - { - case "notification": - // TODO - break; - case "message": - // TODO - break; - } - - await _messageService.Success($"清空了{key}"); - } - - public async Task HandleViewMore(string key) - { - await _messageService.Info("查看更多..."); - } - - public async Task HandleSelectUser(MenuItem item) - { - switch (item.Key) - { - case "center": - _navigationManager.NavigateTo("/account/center"); - break; - case "setting": - _navigationManager.NavigateTo("/account/settings"); - break; - case "logout": - - // 先调用服务端登出接口 TODO - - // 再清楚本地应用token缓存 - await _localStorage.RemoveItemAsync("access_token"); - _httpClient.DefaultRequestHeaders.Authorization = null; - - _navigationManager.NavigateTo("/user/login", true); - break; - default: - break; - } - await Task.CompletedTask; - } - - /// - /// 多语言 - /// - /// - public async Task HandleSelectLang(MenuItem item) - { - var langText = item.Key switch - { - "zh-Hans" => "简体中文", - _ => "English", - }; - string lang = item.Key; - await _localStorage.SetItemAsStringAsync("lang", lang); - - //await _accountAppService.ChangeLanguageAsync(lang); //TODO - - CultureInfo culture = new(lang); - CultureInfo.DefaultThreadCurrentCulture = culture; - CultureInfo.DefaultThreadCurrentUICulture = culture; - - await _messageService.Success($"切换【{langText}】成功!"); - - var currentUrl = _navigationManager.Uri; - _navigationManager.NavigateTo(currentUrl, true); - } + // private readonly HttpClient _httpClient; + // private readonly ILocalStorageService _localStorage; + // private readonly MessageService _messageService; + // private readonly NavigationManager _navigationManager; + // private IDictionary _languageLabels = new Dictionary(); + // private string[] _locales; + // private IDictionary _languageIcons = new Dictionary(); + // public RightContent( + // HttpClient httpClient, + // ILocalStorageService localStorage, + // MessageService messageService, + // NavigationManager navigationManager + // ) + // { + // _httpClient = httpClient; + // _localStorage = localStorage; + // _messageService = messageService; + // _navigationManager = navigationManager; + // } + // + // public string FullScreenTipMsg { get; set; } = "全屏"; + // + // public AvatarMenuItem[] AvatarMenuItems { get; } = new AvatarMenuItem[] + // { + // new() { Key = "setting", IconType = "setting", Option = "个人设置"}, + // new() { Key = "center", IconType = "user", Option = "锁定屏幕"}, + // new() { IsDivider = true }, + // new() { Key = "logout", IconType = "logout", Option = "注销"} + // }; + // protected override async Task OnInitializedAsync() + // { + // await base.OnInitializedAsync(); + // + // ClearClassMap(); + // + // _languageLabels.Add("zh-Hans", "简体中文"); + // _languageLabels.Add("en", "English"); + // + // _languageIcons.Add("zh-Hans", "\ud83c\udde8\ud83c\uddf3"); + // _languageIcons.Add("en", "\ud83c\uddfa\ud83c\uddf8"); + // + // _locales = new string[] { "zh-Hans", "en" }; + // } + // + // private void ClearClassMap() + // { + // ClassMapper.Clear().Add("right"); + // } + // + // public async Task HandleClear(string key) + // { + // switch (key) + // { + // case "notification": + // // TODO + // break; + // case "message": + // // TODO + // break; + // } + // + // await _messageService.Success($"清空了{key}"); + // } + // + // public async Task HandleViewMore(string key) + // { + // await _messageService.Info("查看更多..."); + // } + // + // public async Task HandleSelectUser(MenuItem item) + // { + // switch (item.Key) + // { + // case "center": + // _navigationManager.NavigateTo("/account/center"); + // break; + // case "setting": + // _navigationManager.NavigateTo("/account/settings"); + // break; + // case "logout": + // + // // 先调用服务端登出接口 TODO + // + // // 再清楚本地应用token缓存 + // await _localStorage.RemoveItemAsync("access_token"); + // _httpClient.DefaultRequestHeaders.Authorization = null; + // + // _navigationManager.NavigateTo("/user/login", true); + // break; + // default: + // break; + // } + // await Task.CompletedTask; + // } + // + // /// + // /// 多语言 + // /// + // /// + // public async Task HandleSelectLang(MenuItem item) + // { + // var langText = item.Key switch + // { + // "zh-Hans" => "简体中文", + // _ => "English", + // }; + // string lang = item.Key; + // await _localStorage.SetItemAsStringAsync("lang", lang); + // + // //await _accountAppService.ChangeLanguageAsync(lang); //TODO + // + // CultureInfo culture = new(lang); + // CultureInfo.DefaultThreadCurrentCulture = culture; + // CultureInfo.DefaultThreadCurrentUICulture = culture; + // + // await _messageService.Success($"切换【{langText}】成功!"); + // + // var currentUrl = _navigationManager.Uri; + // _navigationManager.NavigateTo(currentUrl, true); + // } } } diff --git a/aspnet-core/services/src/Lion.AbpPro.Blazor.Layout.AntDesignTheme/Lion.AbpPro.Blazor.Layout.AntDesignTheme.csproj b/aspnet-core/services/src/Lion.AbpPro.Blazor.Layout.AntDesignTheme/Lion.AbpPro.Blazor.Layout.AntDesignTheme.csproj index 7287664b..6b9d9b93 100644 --- a/aspnet-core/services/src/Lion.AbpPro.Blazor.Layout.AntDesignTheme/Lion.AbpPro.Blazor.Layout.AntDesignTheme.csproj +++ b/aspnet-core/services/src/Lion.AbpPro.Blazor.Layout.AntDesignTheme/Lion.AbpPro.Blazor.Layout.AntDesignTheme.csproj @@ -14,13 +14,13 @@ - + - + diff --git a/aspnet-core/services/src/Lion.AbpPro.Blazor.Layout.AntDesignTheme/Pages/Identity/Users/User.razor.cs b/aspnet-core/services/src/Lion.AbpPro.Blazor.Layout.AntDesignTheme/Pages/Identity/Users/User.razor.cs index b8404722..f86fca14 100644 --- a/aspnet-core/services/src/Lion.AbpPro.Blazor.Layout.AntDesignTheme/Pages/Identity/Users/User.razor.cs +++ b/aspnet-core/services/src/Lion.AbpPro.Blazor.Layout.AntDesignTheme/Pages/Identity/Users/User.razor.cs @@ -1,13 +1,22 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Threading.Tasks; +using Lion.AbpPro.Users; +using Lion.AbpPro.Users.Dtos; -namespace Lion.AbpPro.Blazor.Layout.AntDesignTheme.Pages.Identity.Users +namespace Lion.AbpPro.Blazor.Layout.AntDesignTheme.Pages.Identity.Users; + +public partial class User { - public partial class User + private readonly IAccountAppService _accountAppService; + + public User(IAccountAppService accountAppService) { + _accountAppService = accountAppService; + } + protected override async Task OnInitializedAsync() + { + var res = await _accountAppService.LoginAsync(new LoginInput + { Name = "admin", Password = "1q2w3E*" }); + base.OnInitializedAsync(); } -} +} \ No newline at end of file diff --git a/aspnet-core/shared/Lion.AbpPro.Shared.Hosting.Microservices/Lion.AbpPro.Shared.Hosting.Microservices.csproj b/aspnet-core/shared/Lion.AbpPro.Shared.Hosting.Microservices/Lion.AbpPro.Shared.Hosting.Microservices.csproj index 9781b58c..1d2d1fef 100644 --- a/aspnet-core/shared/Lion.AbpPro.Shared.Hosting.Microservices/Lion.AbpPro.Shared.Hosting.Microservices.csproj +++ b/aspnet-core/shared/Lion.AbpPro.Shared.Hosting.Microservices/Lion.AbpPro.Shared.Hosting.Microservices.csproj @@ -15,6 +15,8 @@ + +