You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

544 lines
19 KiB

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Shentun.Peis.EntityFrameworkCore;
using Shentun.Peis.MultiTenancy;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite.Bundling;
using Microsoft.OpenApi.Models;
using OpenIddict.Validation.AspNetCore;
using Volo.Abp;
using Volo.Abp.Account;
using Volo.Abp.Account.Web;
using Volo.Abp.AspNetCore.MultiTenancy;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared;
using Volo.Abp.AspNetCore.Serilog;
using Volo.Abp.Autofac;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.Swashbuckle;
using Volo.Abp.UI.Navigation.Urls;
using Volo.Abp.VirtualFileSystem;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using System.Reflection;
using Swashbuckle.AspNetCore.SwaggerGen;
using Microsoft.AspNetCore.Mvc.Filters;
using Volo.Abp.AspNetCore.Mvc.Validation;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Volo.Abp.Identity;
using Microsoft.Extensions.FileProviders;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Volo.Abp.Settings;
using Volo.Abp.Identity.Settings;
using Microsoft.AspNetCore.Identity;
using Volo.Abp.AspNetCore.Mvc.AntiForgery;
using Microsoft.AspNetCore.Authentication;
using Nito.Disposables.Internals;
using Volo.Abp.AspNetCore.Mvc.ExceptionHandling;
using static IdentityModel.ClaimComparer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Http;
using Shentun.Peis.Filter;
using Shentun.Peis.VirtualPath;
using System.Text.Encodings.Web;
using System.Text.Unicode;
using Volo.Abp.Json;
using Shentun.Utilities;
using Volo.Abp.SecurityLog;
using Volo.Abp.Auditing;
namespace Shentun.Peis;
[DependsOn(
typeof(PeisHttpApiModule),
typeof(AbpAutofacModule),
typeof(AbpAspNetCoreMultiTenancyModule),
typeof(PeisApplicationModule),
typeof(PeisEntityFrameworkCoreModule),
typeof(AbpAspNetCoreMvcUiLeptonXLiteThemeModule),
typeof(AbpAccountWebOpenIddictModule),
typeof(AbpAspNetCoreSerilogModule),
typeof(AbpSwashbuckleModule)
)]
public class PeisHttpApiHostModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<OpenIddictBuilder>(builder =>
{
builder.AddValidation(options =>
{
options.AddAudiences("Peis");
options.UseLocalServer();
options.UseAspNetCore();
});
});
//重写定义token失效时间 接口返回的是秒
PreConfigure<OpenIddictServerBuilder>(builder =>
{
//builder.SetAccessTokenLifetime(TimeSpan.FromHours(8)).SetRefreshTokenLifetime(TimeSpan.FromDays(15));
builder.SetAccessTokenLifetime(TimeSpan.FromDays(30)).SetRefreshTokenLifetime(TimeSpan.FromDays(60));
});
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
var hostingEnvironment = context.Services.GetHostingEnvironment();
ConfigureAuthentication(context);
ConfigureBundles();
ConfigureUrls(configuration);
ConfigureConventionalControllers();
ConfigureLocalization();
ConfigureVirtualFileSystem(context);
ConfigureCors(context, configuration);
ConfigureSwaggerServices(context, configuration);
ConfigureJsonOptions(); //全局配置api返回值中的日期默认格式
//密码策略配置
context.Services.Configure<IdentityOptions>(opt =>
{
opt.Password.RequireDigit = false;
opt.Password.RequireLowercase = false;
opt.Password.RequireUppercase = false;
opt.Password.RequireNonAlphanumeric = false;
opt.Password.RequiredLength = 1;
});
//密码策略配置
context.Services.Configure<IdentityOptions>(opt =>
{
opt.Password.RequireDigit = false;
opt.Password.RequireLowercase = false;
opt.Password.RequireUppercase = false;
opt.Password.RequireNonAlphanumeric = false;
opt.Password.RequiredLength = 1;
});
#region 临时去掉日志
//关闭审计日志
Configure<AbpAuditingOptions>(options =>
{
options.IsEnabled = false;
});
//关闭安全日志
Configure<AbpSecurityLogOptions>(options =>
{
options.IsEnabled = false;
});
#endregion
//防伪令牌
//context.Services.Configure<AbpAntiForgeryOptions>(opt =>
//{
// opt.AutoValidate = false;
//});
context.Services.AddMvc(options =>
{
var filterMetadata = options.Filters.FirstOrDefault(x => x is ServiceFilterAttribute attribute && attribute.ServiceType.Equals(typeof(AbpValidationActionFilter)));
options.Filters.Remove(filterMetadata);
options.Filters.Add(typeof(ValidateFilter));
options.Filters.Add(typeof(CustomerExceptionFilterAttribute));
options.Filters.Add(typeof(CustomerActionFilterAttribute));
// options.Filters.ReplaceOne(x => (x as ServiceFilterAttribute)?.ServiceType?.Name == nameof(ExceptionFilterAttribute), new ServiceFilterAttribute(typeof(ABCExceptionFilterAttribute)));
// options.Filters.ReplaceOne(x => (x as ServiceFilterAttribute)?.ServiceType?.Name == nameof(AbpExceptionFilter), new ServiceFilterAttribute(typeof(MyExceptionFilter)));
});
//context.Services.TryAddTransient<IAuthorizationMiddlewareResultHandler, AuthorizationMiddlewareResultHandler>();
///解除https限制
context.Services.AddOpenIddict()
.AddServer(option =>
{
option.UseAspNetCore().DisableTransportSecurityRequirement();
});
//虚拟目录
context.Services.AddSingleton(new MyFileProvider(configuration["VirtualPath:RealPath"], configuration["VirtualPath:Alias"]));
/*
Configure<AbpAspNetCoreMvcOptions>(options =>
{
options.ConventionalControllers
.Create(typeof(PeisApplicationModule).Assembly, opts =>
{
opts.RootPath = "api/app";
opts.UrlControllerNameNormalizer = (controller) =>
{
return controller.ControllerName;
};
opts.UrlActionNameNormalizer = (action) =>
{
return action.Action.ActionName;
};
});
});
*/
}
/// <summary>
/// 全局转换日期格式
/// </summary>
private void ConfigureJsonOptions()
{
//context.Services.AddControllers().AddJsonOptions(options =>
//{
// options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All);
// options.JsonSerializerOptions.PropertyNamingPolicy = null;
//});
Configure<JsonOptions>(x =>
{
//x.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All);
x.JsonSerializerOptions.Converters.Add(new DateTimeJsonConverter());
x.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
});
//Configure<AbpJsonOptions>(x =>
//{
// x.DefaultDateTimeFormat = "yyyy-MM-dd HH:mm:ss";
//});
}
private void ConfigureAuthentication(ServiceConfigurationContext context)
{
context.Services.ForwardIdentityAuthenticationForBearer(OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme);
}
private void ConfigureBundles()
{
Configure<AbpBundlingOptions>(options =>
{
options.StyleBundles.Configure(
LeptonXLiteThemeBundles.Styles.Global,
bundle =>
{
bundle.AddFiles("/global-styles.css");
}
);
});
}
private void ConfigureUrls(IConfiguration configuration)
{
Configure<AppUrlOptions>(options =>
{
options.Applications["MVC"].RootUrl = configuration["App:SelfUrl"];
options.RedirectAllowedUrls.AddRange(configuration["App:RedirectAllowedUrls"].Split(','));
options.Applications["Angular"].RootUrl = configuration["App:ClientUrl"];
options.Applications["Angular"].Urls[AccountUrlNames.PasswordReset] = "account/reset-password";
});
}
private void ConfigureVirtualFileSystem(ServiceConfigurationContext context)
{
var hostingEnvironment = context.Services.GetHostingEnvironment();
if (hostingEnvironment.IsDevelopment())
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.ReplaceEmbeddedByPhysical<PeisDomainSharedModule>(
Path.Combine(hostingEnvironment.ContentRootPath,
$"..{Path.DirectorySeparatorChar}Shentun.Peis.Domain.Shared"));
options.FileSets.ReplaceEmbeddedByPhysical<PeisDomainModule>(
Path.Combine(hostingEnvironment.ContentRootPath,
$"..{Path.DirectorySeparatorChar}Shentun.Peis.Domain"));
options.FileSets.ReplaceEmbeddedByPhysical<PeisApplicationContractsModule>(
Path.Combine(hostingEnvironment.ContentRootPath,
$"..{Path.DirectorySeparatorChar}Shentun.Peis.Application.Contracts"));
options.FileSets.ReplaceEmbeddedByPhysical<PeisApplicationModule>(
Path.Combine(hostingEnvironment.ContentRootPath,
$"..{Path.DirectorySeparatorChar}Shentun.Peis.Application"));
});
}
}
private void ConfigureConventionalControllers()
{
#region 配置隐藏api
Configure<MvcOptions>(options =>
{
options.Conventions.Add(new ApplicationDescription());
});
#endregion
Configure<AbpAspNetCoreMvcOptions>(options =>
{
options.ConventionalControllers.Create(typeof(PeisApplicationModule).Assembly);
});
}
private static void ConfigureSwaggerServices(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.AddAbpSwaggerGenWithOAuth(
configuration["AuthServer:Authority"],
new Dictionary<string, string>
{
{"Peis", "Peis API"}
},
options =>
{
//options.SwaggerDoc("v1", new OpenApiInfo { Title = "Peis API", Version = "v1" });
//options.DocInclusionPredicate((docName, description) => true);
//options.CustomSchemaIds(type => type.FullName);
options.SwaggerDoc("Work", new OpenApiInfo { Title = "业务API", Version = "V1", Description = "业务API" });
options.SwaggerDoc("Sys", new OpenApiInfo { Title = "底层API", Version = "V1", Description = "底层API" });
options.DocInclusionPredicate((docName, description) =>
{
if (!description.TryGetMethodInfo(out MethodInfo method))
{
return false;
}
/*使用ApiExplorerSettingsAttribute里面的GroupName进行特性标识
* DeclaringType只能获取controller上的特性
* 我们这里是想以action的特性为主
* */
var version = method.DeclaringType.GetCustomAttributes(true).OfType<ApiExplorerSettingsAttribute>().Select(m => m.GroupName);
if (version.Any())
{
if (version.Any(v => v == docName))
//选择了sys,并且分组不为User
return true;
}
else
{
if (docName == "Sys")
{
return true;
}
}
//这里获取action的特性
var actionVersion = method.GetCustomAttributes(true).OfType<ApiExplorerSettingsAttribute>().Select(m => m.GroupName);
if (actionVersion.Any())
{
return actionVersion.Any(v => v == docName);
}
return false;
});
});
}
private void ConfigureLocalization()
{
Configure<AbpLocalizationOptions>(options =>
{
options.Languages.Add(new LanguageInfo("ar", "ar", "العربية"));
options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština"));
options.Languages.Add(new LanguageInfo("en", "en", "English"));
options.Languages.Add(new LanguageInfo("en-GB", "en-GB", "English (UK)"));
options.Languages.Add(new LanguageInfo("fi", "fi", "Finnish"));
options.Languages.Add(new LanguageInfo("fr", "fr", "Français"));
options.Languages.Add(new LanguageInfo("hi", "hi", "Hindi", "in"));
options.Languages.Add(new LanguageInfo("is", "is", "Icelandic", "is"));
options.Languages.Add(new LanguageInfo("it", "it", "Italiano", "it"));
options.Languages.Add(new LanguageInfo("hu", "hu", "Magyar"));
options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português"));
options.Languages.Add(new LanguageInfo("ro-RO", "ro-RO", "Română"));
options.Languages.Add(new LanguageInfo("ru", "ru", "Русский"));
options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak"));
options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe"));
options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文"));
options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文"));
options.Languages.Add(new LanguageInfo("de-DE", "de-DE", "Deutsch", "de"));
options.Languages.Add(new LanguageInfo("es", "es", "Español", "es"));
options.Languages.Add(new LanguageInfo("el", "el", "Ελληνικά"));
});
}
private void ConfigureCors(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.AddCors(options =>
{
options.AddDefaultPolicy(builder =>
{
builder
.WithOrigins(
configuration["App:CorsOrigins"]
.Split(",", StringSplitOptions.RemoveEmptyEntries)
.Select(o => o.RemovePostFix("/"))
.ToArray()
)
.WithAbpExposedHeaders()
.SetIsOriginAllowedToAllowWildcardSubdomains()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
//添加swagger中文注释
context.Services.AddSwaggerGen(options =>
{
//var baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
var baseDirectory = AppContext.BaseDirectory;
//Serilog.Log.Information("swagger地址1:" + baseDirectory);
//var baseDirectory2 = Path.GetDirectoryName(typeof(Program).Assembly.Location);
//Serilog.Log.Information("swagger地址2:" + baseDirectory2);
//var baseDirectory3 = AppDomain.CurrentDomain.BaseDirectory;
//Serilog.Log.Information("swagger地址3:" + baseDirectory3);
var commentsFile = Path.Combine(baseDirectory, "Shentun.Peis.Application.xml");
options.IncludeXmlComments(commentsFile, true);
var commentsFileDro = Path.Combine(baseDirectory, "Shentun.Peis.Application.Contracts.xml");
options.IncludeXmlComments(commentsFileDro, true);
var commentsFileapi = Path.Combine(baseDirectory, "Shentun.Peis.HttpApi.xml");
options.IncludeXmlComments(commentsFileapi, true);
});
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
var env = context.GetEnvironment();
var configuration = context.GetConfiguration();
//请求错误提示配置
app.UseErrorHandling();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseAbpRequestLocalization();
if (!env.IsDevelopment())
{
app.UseErrorPage();
}
app.UseCorrelationId();
//var staticFile = new StaticFileOptions();
//var filePath = env.ContentRootPath+"UpLoad\\";
////var filePath = env.ContentRootPath ;
//staticFile.FileProvider = new PhysicalFileProvider(filePath);
//app.UseStaticFiles(new StaticFileOptions
//{
// FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "UpLoad")),
// RequestPath="/UpLoad"
//});
app.UseStaticFiles();
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "ReportFile")),
RequestPath = "/ReportFile"
});
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "UpLoad")),
RequestPath = "/photo"
});
//虚拟目录
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(configuration["VirtualPath:RealPath"]),
RequestPath = configuration["VirtualPath:RequestPath"]
});
app.UseRouting();
app.UseCors();
app.UseAuthentication();
app.UseAbpOpenIddictValidation();
if (MultiTenancyConsts.IsEnabled)
{
app.UseMultiTenancy();
}
app.UseUnitOfWork();
app.UseAuthorization();
//app.UseMiddleware(typeof(AuthorizationMiddlewareResultHandler));
app.UseSwagger();
app.UseAbpSwaggerUI(c =>
{
//c.SwaggerEndpoint("/swagger/v1/swagger.json", "Peis API");
c.SwaggerEndpoint($"/swagger/Work/swagger.json", "业务API"); //分组显示
c.SwaggerEndpoint($"/swagger/Sys/swagger.json", "底层API"); //分组显示
//c.RoutePrefix = string.Empty; // url 中不显示swagger
var configuration = context.ServiceProvider.GetRequiredService<IConfiguration>();
c.OAuthClientId(configuration["AuthServer:SwaggerClientId"]);
c.OAuthScopes("Peis");
c.DefaultModelExpandDepth(-1);
});
app.UseAuditing();
app.UseAbpSerilogEnrichers();
app.UseConfiguredEndpoints();
}
}