Files
Yi.Admin/Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs

418 lines
17 KiB
C#
Raw Normal View History

using System.Globalization;
2024-02-26 13:42:37 +08:00
using System.Text;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
2024-02-26 13:42:37 +08:00
using System.Threading.RateLimiting;
2024-11-15 16:45:01 +08:00
using Hangfire;
2024-11-15 17:01:39 +08:00
using Hangfire.MemoryStorage;
2024-11-15 16:45:01 +08:00
using Hangfire.Redis.StackExchange;
2023-12-11 09:55:12 +08:00
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
2024-11-10 22:31:56 +08:00
using Microsoft.AspNetCore.StaticFiles;
2023-12-11 09:55:12 +08:00
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
2024-11-15 16:45:01 +08:00
using StackExchange.Redis;
using Volo.Abp.AspNetCore.Auditing;
2023-12-11 09:55:12 +08:00
using Volo.Abp.AspNetCore.Authentication.JwtBearer;
2024-08-13 16:45:56 +08:00
using Volo.Abp.AspNetCore.ExceptionHandling;
2024-01-21 00:26:21 +08:00
using Volo.Abp.AspNetCore.MultiTenancy;
2023-12-11 09:55:12 +08:00
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.AntiForgery;
using Volo.Abp.AspNetCore.Serilog;
using Volo.Abp.Auditing;
using Volo.Abp.Autofac;
2025-03-08 22:14:26 +08:00
using Volo.Abp.BackgroundWorkers;
using Volo.Abp.Caching;
2024-01-21 18:11:04 +08:00
using Volo.Abp.MultiTenancy;
2023-12-11 09:55:12 +08:00
using Volo.Abp.Swashbuckle;
using Yi.Abp.Application;
using Yi.Abp.SqlsugarCore;
2025-06-19 21:24:13 +08:00
using Yi.Framework.AiHub.Application;
2023-12-11 09:55:12 +08:00
using Yi.Framework.AspNetCore;
using Yi.Framework.AspNetCore.Authentication.OAuth;
using Yi.Framework.AspNetCore.Authentication.OAuth.Gitee;
using Yi.Framework.AspNetCore.Authentication.OAuth.QQ;
2023-12-11 09:55:12 +08:00
using Yi.Framework.AspNetCore.Microsoft.AspNetCore.Builder;
using Yi.Framework.AspNetCore.Microsoft.Extensions.DependencyInjection;
2024-11-15 18:17:53 +08:00
using Yi.Framework.BackgroundWorkers.Hangfire;
2023-12-11 21:14:12 +08:00
using Yi.Framework.Bbs.Application;
2024-08-14 12:50:28 +08:00
using Yi.Framework.Bbs.Application.Extensions;
2024-04-04 14:00:32 +08:00
using Yi.Framework.ChatHub.Application;
2024-02-16 21:06:34 +08:00
using Yi.Framework.CodeGen.Application;
2024-10-26 15:40:45 +08:00
using Yi.Framework.Core.Json;
2024-10-24 21:39:20 +08:00
using Yi.Framework.DigitalCollectibles.Application;
2023-12-11 09:55:12 +08:00
using Yi.Framework.Rbac.Application;
using Yi.Framework.Rbac.Domain.Authorization;
2024-01-24 11:26:44 +08:00
using Yi.Framework.Rbac.Domain.Shared.Consts;
2023-12-11 09:55:12 +08:00
using Yi.Framework.Rbac.Domain.Shared.Options;
2025-03-01 00:12:56 +08:00
using Yi.Framework.Stock.Application;
2024-02-06 15:25:17 +08:00
using Yi.Framework.TenantManagement.Application;
2023-12-11 09:55:12 +08:00
namespace Yi.Abp.Web
{
[DependsOn(
2023-12-12 17:56:11 +08:00
typeof(YiAbpSqlSugarCoreModule),
2023-12-11 09:55:12 +08:00
typeof(YiAbpApplicationModule),
2024-01-21 00:26:21 +08:00
typeof(AbpAspNetCoreMultiTenancyModule),
2023-12-11 09:55:12 +08:00
typeof(AbpAspNetCoreMvcModule),
2025-02-23 01:31:30 +08:00
2023-12-11 09:55:12 +08:00
typeof(AbpSwashbuckleModule),
typeof(AbpAspNetCoreSerilogModule),
typeof(AbpAuditingModule),
typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
typeof(YiFrameworkAspNetCoreModule),
2025-02-23 01:31:30 +08:00
typeof(YiFrameworkAspNetCoreAuthenticationOAuthModule),
typeof(YiFrameworkBackgroundWorkersHangfireModule),
typeof(AbpAutofacModule)
2024-08-14 12:50:28 +08:00
)]
2023-12-11 09:55:12 +08:00
public class YiAbpWebModule : AbpModule
{
private const string DefaultCorsPolicyName = "Default";
2024-08-14 12:50:28 +08:00
2024-11-29 18:01:54 +08:00
public override void PreConfigureServices(ServiceConfigurationContext context)
{
//动态Api-改进在pre中配置启动更快
PreConfigure<AbpAspNetCoreMvcOptions>(options =>
{
options.ConventionalControllers.Create(typeof(YiAbpApplicationModule).Assembly,
options => options.RemoteServiceName = "default");
options.ConventionalControllers.Create(typeof(YiFrameworkRbacApplicationModule).Assembly,
options => options.RemoteServiceName = "rbac");
options.ConventionalControllers.Create(typeof(YiFrameworkBbsApplicationModule).Assembly,
options => options.RemoteServiceName = "bbs");
options.ConventionalControllers.Create(typeof(YiFrameworkChatHubApplicationModule).Assembly,
options => options.RemoteServiceName = "chat-hub");
2024-11-30 23:53:24 +08:00
options.ConventionalControllers.Create(typeof(YiFrameworkTenantManagementApplicationModule).Assembly,
2024-11-29 18:01:54 +08:00
options => options.RemoteServiceName = "tenant-management");
options.ConventionalControllers.Create(typeof(YiFrameworkCodeGenApplicationModule).Assembly,
options => options.RemoteServiceName = "code-gen");
2024-11-30 23:53:24 +08:00
options.ConventionalControllers.Create(typeof(YiFrameworkDigitalCollectiblesApplicationModule).Assembly,
options => options.RemoteServiceName = "digital-collectibles");
2025-03-01 00:12:56 +08:00
options.ConventionalControllers.Create(typeof(YiFrameworkStockApplicationModule).Assembly,
2025-03-02 01:54:12 +08:00
options => options.RemoteServiceName = "ai-stock");
2025-06-19 21:24:13 +08:00
options.ConventionalControllers.Create(typeof(YiFrameworkAiHubApplicationModule).Assembly,
options => options.RemoteServiceName = "ai-hub");
2024-11-29 18:01:54 +08:00
//统一前缀
options.ConventionalControllers.ConventionalControllerSettings.ForEach(x => x.RootPath = "api/app");
});
}
2023-12-11 09:55:12 +08:00
public override Task ConfigureServicesAsync(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
2023-12-12 17:16:28 +08:00
var host = context.Services.GetHostingEnvironment();
2023-12-11 09:55:12 +08:00
var service = context.Services;
2024-11-19 16:36:33 +08:00
2025-03-08 22:14:26 +08:00
//本地开发环境,禁用作业执行
if (host.IsDevelopment())
{
Configure<AbpBackgroundWorkerOptions> (options =>
{
options.IsEnabled = false;
});
}
2023-12-11 09:55:12 +08:00
//请求日志
Configure<AbpAuditingOptions>(options =>
2023-12-11 09:55:12 +08:00
{
2024-01-23 15:08:01 +08:00
//默认关闭,开启会有大量的审计日志
2025-01-19 15:17:48 +08:00
options.IsEnabled = false;
2023-12-11 09:55:12 +08:00
});
2024-11-15 16:45:01 +08:00
//忽略审计日志路径
Configure<AbpAspNetCoreAuditingOptions>(options =>
2023-12-11 09:55:12 +08:00
{
2024-11-15 16:45:01 +08:00
options.IgnoredUrls.Add("/api/app/file/");
options.IgnoredUrls.Add("/hangfire");
2023-12-11 09:55:12 +08:00
});
2024-11-19 16:36:33 +08:00
//采用furion格式的规范化api默认不开启使用abp优雅的方式
2024-11-19 16:36:33 +08:00
//你没看错。。。
//service.AddFurionUnifyResultApi();
2024-11-19 16:36:33 +08:00
//配置错误处理显示详情
Configure<AbpExceptionHandlingOptions>(options => { options.SendExceptionsDetailsToClients = true; });
2023-12-11 09:55:12 +08:00
2024-11-19 16:36:33 +08:00
//【NewtonsoftJson严重问题逆天】设置api格式留给后人铭记
// service.AddControllers().AddNewtonsoftJson(options =>
// {
// options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
// options.SerializerSettings.Converters.Add(new StringEnumConverter());
// });
2023-12-12 14:33:32 +08:00
2024-11-19 16:36:33 +08:00
//请使用微软的注意abp date又包了一层采用DefaultJsonTypeInfoResolver统一覆盖
Configure<JsonOptions>(options =>
{
options.JsonSerializerOptions.TypeInfoResolver = new DefaultJsonTypeInfoResolver();
options.JsonSerializerOptions.Converters.Add(new DatetimeJsonConverter());
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
});
2023-12-11 09:55:12 +08:00
2024-11-19 16:36:33 +08:00
//设置缓存不要过期默认滑动20分钟
Configure<AbpDistributedCacheOptions>(cacheOptions =>
{
cacheOptions.GlobalCacheEntryOptions.SlidingExpiration = null;
//缓存key前缀
cacheOptions.KeyPrefix = "Yi:";
});
2024-08-14 12:50:28 +08:00
2024-11-19 16:36:33 +08:00
Configure<AbpAntiForgeryOptions>(options => { options.AutoValidate = false; });
2023-12-11 09:55:12 +08:00
2024-11-19 16:36:33 +08:00
//Swagger
context.Services.AddYiSwaggerGen<YiAbpWebModule>(options =>
{
options.SwaggerDoc("default",
new OpenApiInfo { Title = "Yi.Framework.Abp", Version = "v1", Description = "集大成者" });
});
2023-12-11 09:55:12 +08:00
2024-11-19 16:36:33 +08:00
//跨域
context.Services.AddCors(options =>
{
options.AddPolicy(DefaultCorsPolicyName, builder =>
2024-02-26 13:42:37 +08:00
{
2024-11-19 16:36:33 +08:00
builder
.WithOrigins(
configuration["App:CorsOrigins"]!
.Split(";", StringSplitOptions.RemoveEmptyEntries)
.Select(o => o.RemovePostFix("/"))
.ToArray()
)
.WithAbpExposedHeaders()
.SetIsOriginAllowedToAllowWildcardSubdomains()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
2024-11-15 16:45:01 +08:00
});
2024-11-19 16:36:33 +08:00
});
2024-11-19 16:36:33 +08:00
//配置多租户
Configure<AbpTenantResolveOptions>(options =>
{
//基于cookie jwt不好用有坑
options.TenantResolvers.Clear();
options.TenantResolvers.Add(new HeaderTenantResolveContributor());
//options.TenantResolvers.Add(new HeaderTenantResolveContributor());
//options.TenantResolvers.Add(new CookieTenantResolveContributor());
//options.TenantResolvers.RemoveAll(x => x.Name == CookieTenantResolveContributor.ContributorName);
});
2024-01-21 00:26:21 +08:00
2024-11-19 16:36:33 +08:00
//配置Hangfire定时任务存储开启redis后优先使用redis
var redisConfiguration = configuration["Redis:Configuration"];
2024-11-19 18:38:58 +08:00
context.Services.AddHangfire(config=>
2024-11-19 16:36:33 +08:00
{
2025-03-18 23:13:16 +08:00
var redisEnabled=configuration.GetSection("Redis").GetValue<bool>("IsEnabled");
2025-02-07 17:52:38 +08:00
if (redisEnabled)
2024-02-26 13:42:37 +08:00
{
2025-03-10 22:27:54 +08:00
var jobDb=configuration.GetSection("Redis").GetValue<int>("JobDb");
2024-11-19 16:36:33 +08:00
config.UseRedisStorage(
ConnectionMultiplexer.Connect(redisConfiguration),
new RedisStorageOptions()
{
2025-03-10 22:27:54 +08:00
Db =jobDb,
2024-11-19 16:36:33 +08:00
InvisibilityTimeout = TimeSpan.FromHours(1), //JOB允许执行1小时
Prefix = "Yi:HangfireJob:"
}).WithJobExpirationTimeout(TimeSpan.FromHours(1));
}
else
{
config.UseMemoryStorage();
}
});
2024-08-14 12:50:28 +08:00
2024-11-19 16:36:33 +08:00
//速率限制
//每60秒限制100个请求滑块添加分6段
service.AddRateLimiter(_ =>
{
_.RejectionStatusCode = StatusCodes.Status429TooManyRequests;
_.OnRejected = (context, _) =>
2024-11-15 16:45:01 +08:00
{
2024-11-19 16:36:33 +08:00
if (context.Lease.TryGetMetadata(MetadataName.RetryAfter, out var retryAfter))
2024-08-14 12:50:28 +08:00
{
2024-11-19 16:36:33 +08:00
context.HttpContext.Response.Headers.RetryAfter =
((int)retryAfter.TotalSeconds).ToString(NumberFormatInfo.InvariantInfo);
}
2024-02-26 13:42:37 +08:00
2024-11-19 16:36:33 +08:00
context.HttpContext.Response.StatusCode = StatusCodes.Status429TooManyRequests;
context.HttpContext.Response.WriteAsync("Too many requests. Please try again later.");
2024-02-26 13:42:37 +08:00
2024-11-19 16:36:33 +08:00
return new ValueTask();
};
2024-08-14 12:50:28 +08:00
2024-11-19 16:36:33 +08:00
//全局使用,链式表达式
_.GlobalLimiter = PartitionedRateLimiter.CreateChained(
PartitionedRateLimiter.Create<HttpContext, string>(httpContext =>
{
var userAgent = httpContext.Request.Headers.UserAgent.ToString();
2024-11-15 16:45:01 +08:00
2024-11-19 16:36:33 +08:00
return RateLimitPartition.GetSlidingWindowLimiter
(userAgent, _ =>
new SlidingWindowRateLimiterOptions
{
PermitLimit = 1000,
Window = TimeSpan.FromSeconds(60),
SegmentsPerWindow = 6,
QueueProcessingOrder = QueueProcessingOrder.OldestFirst
});
}));
});
2024-02-26 13:42:37 +08:00
2024-11-19 16:36:33 +08:00
//jwt鉴权
var jwtOptions = configuration.GetSection(nameof(JwtOptions)).Get<JwtOptions>();
var refreshJwtOptions = configuration.GetSection(nameof(RefreshJwtOptions)).Get<RefreshJwtOptions>();
2024-11-19 16:36:33 +08:00
context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
2024-02-26 13:42:37 +08:00
{
2024-11-19 16:36:33 +08:00
ClockSkew = TimeSpan.Zero,
ValidateIssuerSigningKey = true,
ValidIssuer = jwtOptions.Issuer,
ValidAudience = jwtOptions.Audience,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtOptions.SecurityKey))
};
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
2023-12-11 09:55:12 +08:00
{
2024-11-19 16:36:33 +08:00
//优先Query中获取再去cookies中获取
var accessToken = context.Request.Query["access_token"];
if (!string.IsNullOrEmpty(accessToken))
2024-08-14 12:50:28 +08:00
{
2024-11-19 16:36:33 +08:00
context.Token = accessToken;
}
else
{
if (context.Request.Cookies.TryGetValue("Token", out var cookiesToken))
2024-11-16 13:10:06 +08:00
{
2024-11-19 16:36:33 +08:00
context.Token = cookiesToken;
2024-11-16 13:10:06 +08:00
}
2024-11-15 16:45:01 +08:00
}
2024-11-19 16:36:33 +08:00
return Task.CompletedTask;
}
};
})
.AddJwtBearer(TokenTypeConst.Refresh, options =>
{
options.TokenValidationParameters = new TokenValidationParameters
2024-02-26 13:42:37 +08:00
{
2024-11-19 16:36:33 +08:00
ClockSkew = TimeSpan.Zero,
ValidateIssuerSigningKey = true,
ValidIssuer = refreshJwtOptions.Issuer,
ValidAudience = refreshJwtOptions.Audience,
IssuerSigningKey =
new SymmetricSecurityKey(Encoding.UTF8.GetBytes(refreshJwtOptions.SecurityKey))
};
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
2024-01-24 11:26:44 +08:00
{
2024-11-19 16:36:33 +08:00
var refresh_token = context.Request.Headers["refresh_token"];
if (!string.IsNullOrEmpty(refresh_token))
2024-08-14 12:50:28 +08:00
{
2024-11-19 16:36:33 +08:00
context.Token = refresh_token;
2024-11-15 16:45:01 +08:00
return Task.CompletedTask;
2024-08-14 12:50:28 +08:00
}
2024-11-19 16:36:33 +08:00
var refreshToken = context.Request.Query["refresh_token"];
if (!string.IsNullOrEmpty(refreshToken))
{
context.Token = refreshToken;
}
2023-12-11 09:55:12 +08:00
2024-11-19 16:36:33 +08:00
return Task.CompletedTask;
}
};
})
.AddQQ(options => { configuration.GetSection("OAuth:QQ").Bind(options); })
.AddGitee(options => { configuration.GetSection("OAuth:Gitee").Bind(options); });
//授权
context.Services.AddAuthorization();
return Task.CompletedTask;
}
2023-12-11 09:55:12 +08:00
2024-11-15 16:45:01 +08:00
public override async Task OnApplicationInitializationAsync(ApplicationInitializationContext context)
2023-12-11 09:55:12 +08:00
{
var service = context.ServiceProvider;
var env = context.GetEnvironment();
var app = context.GetApplicationBuilder();
app.UseRouting();
2023-12-11 22:14:13 +08:00
2023-12-11 21:14:12 +08:00
//跨域
2023-12-11 09:55:12 +08:00
app.UseCors(DefaultCorsPolicyName);
2023-12-11 22:14:13 +08:00
if (!env.IsDevelopment())
{
//速率限制
app.UseRateLimiter();
}
2024-02-26 13:42:37 +08:00
//无感token先刷新再鉴权
app.UseRefreshToken();
2023-12-11 21:14:12 +08:00
//鉴权
2023-12-11 09:55:12 +08:00
app.UseAuthentication();
2024-01-21 00:26:21 +08:00
//多租户
app.UseMultiTenancy();
2023-12-11 21:14:12 +08:00
//swagger
2023-12-11 09:55:12 +08:00
app.UseYiSwagger();
2024-01-05 23:05:13 +08:00
2024-08-14 22:23:54 +08:00
//流量访问统计,需redis支持否则不生效
app.UseAccessLog();
2024-08-14 12:50:28 +08:00
2024-01-02 23:26:05 +08:00
//请求处理
app.UseApiInfoHandling();
2024-01-02 23:26:05 +08:00
2023-12-28 20:24:49 +08:00
//静态资源
2024-11-10 22:31:56 +08:00
app.UseStaticFiles(new StaticFileOptions
{
RequestPath = "/api/app/wwwroot",
// 可以在这里添加或修改MIME类型映射
ContentTypeProvider = new FileExtensionContentTypeProvider
{
Mappings =
{
[".wxss"] = "text/css"
}
}
});
2023-12-28 20:24:49 +08:00
app.UseDefaultFiles();
app.UseDirectoryBrowser("/api/app/wwwroot");
2023-12-11 21:14:12 +08:00
// app.Properties.Add("_AbpExceptionHandlingMiddleware_Added",false);
2023-12-11 21:14:12 +08:00
//工作单元
2023-12-11 09:55:12 +08:00
app.UseUnitOfWork();
2023-12-11 21:14:12 +08:00
//授权
2023-12-11 09:55:12 +08:00
app.UseAuthorization();
2023-12-11 21:14:12 +08:00
//审计日志
2023-12-11 09:55:12 +08:00
app.UseAuditing();
2023-12-11 21:14:12 +08:00
//日志记录
2023-12-11 09:55:12 +08:00
app.UseAbpSerilogEnrichers();
2024-11-19 16:36:33 +08:00
2024-11-16 13:10:06 +08:00
//Hangfire定时任务面板可配置授权意框架支持jwt
2024-11-19 16:36:33 +08:00
app.UseAbpHangfireDashboard("/hangfire",
options =>
{
options.AsyncAuthorization = new[] { new YiTokenAuthorizationFilter(app.ApplicationServices) };
});
2023-12-11 09:55:12 +08:00
2023-12-11 21:14:12 +08:00
//终节点
2023-12-11 09:55:12 +08:00
app.UseConfiguredEndpoints();
}
}
2024-08-14 12:50:28 +08:00
}