using Autofac; using Autofac.Extensions.DependencyInjection; using CSRedis; using Hangfire; using Hangfire.Dashboard; using Hangfire.MemoryStorage; using JiebaNet.Segmenter; using Masuit.LuceneEFCore.SearchEngine; using Masuit.LuceneEFCore.SearchEngine.Extensions; using Masuit.MyBlogs.Core.Common; using Masuit.MyBlogs.Core.Configs; using Masuit.MyBlogs.Core.Extensions; using Masuit.MyBlogs.Core.Extensions.Hangfire; using Masuit.MyBlogs.Core.Hubs; using Masuit.MyBlogs.Core.Infrastructure; using Masuit.MyBlogs.Core.Models.DTO; using Masuit.MyBlogs.Core.Models.ViewModel; using Masuit.Tools; using Masuit.Tools.AspNetCore.Mime; using Masuit.Tools.Core.AspNetCore; using Masuit.Tools.Core.Config; using Masuit.Tools.Core.Net; using Masuit.Tools.Systems; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.HttpOverrides; using Microsoft.AspNetCore.Rewrite; using Microsoft.AspNetCore.StaticFiles; using Microsoft.AspNetCore.WebSockets; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Primitives; using Microsoft.Net.Http.Headers; using StackExchange.Profiling; using System; using System.IO; using System.Linq; using System.Net.Http; using System.Threading.Tasks; using IWebHostEnvironment = Microsoft.AspNetCore.Hosting.IWebHostEnvironment; using SameSiteMode = Microsoft.AspNetCore.Http.SameSiteMode; namespace Masuit.MyBlogs.Core { /// /// asp.net core核心配置 /// public class Startup { /// /// 依赖注入容器 /// public static IServiceProvider ServiceProvider { get; private set; } /// /// 配置中心 /// public IConfiguration Configuration { get; set; } private readonly IWebHostEnvironment _env; /// /// asp.net core核心配置 /// /// public Startup(IConfiguration configuration, IWebHostEnvironment env) { _env = env; void BindConfig() { Configuration = configuration; AppConfig.ConnString = configuration[nameof(AppConfig.ConnString)]; AppConfig.BaiduAK = configuration[nameof(AppConfig.BaiduAK)]; AppConfig.Redis = configuration[nameof(AppConfig.Redis)]; AppConfig.TrueClientIPHeader = configuration[nameof(AppConfig.TrueClientIPHeader)] ?? "CF-Connecting-IP"; AppConfig.EnableIPDirect = bool.Parse(configuration[nameof(AppConfig.EnableIPDirect)] ?? "false"); configuration.Bind("Imgbed:AliyunOSS", AppConfig.AliOssConfig); configuration.Bind("Imgbed:Gitlabs", AppConfig.GitlabConfigs); configuration.AddToMasuitTools(); } ChangeToken.OnChange(configuration.GetReloadToken, BindConfig); BindConfig(); } /// /// ConfigureServices /// /// /// public void ConfigureServices(IServiceCollection services) { RedisHelper.Initialization(new CSRedisClient(AppConfig.Redis)); services.Configure(options => { options.MinimumSameSitePolicy = SameSiteMode.None; }); //配置Cookie策略 services.AddDbContext(opt => { opt.UseMySql(AppConfig.ConnString, builder => builder.EnableRetryOnFailure(3)).EnableDetailedErrors().EnableSensitiveDataLogging(); //opt.UseSqlServer(AppConfig.ConnString); }); //配置数据库 services.Configure(options => { options.MultipartBodyLengthLimit = 104857600; // 100MB }); //配置请求长度 services.AddSession().AddAntiforgery(); //注入Session services.AddWebSockets(opt => opt.ReceiveBufferSize = 4096 * 1024).AddSignalR().AddNewtonsoftJsonProtocol(); services.AddHttpsRedirection(options => { options.RedirectStatusCode = StatusCodes.Status301MovedPermanently; }); services.AddResponseCache().AddCacheConfig(); services.AddHangfire((provider, configuration) => { configuration.UseFilter(new AutomaticRetryAttribute()); configuration.UseMemoryStorage(); }); //配置hangfire services.AddSevenZipCompressor().AddResumeFileResult().AddSearchEngine(new LuceneIndexerOptions() { Path = "lucene" }); // 配置7z和断点续传和Redis和Lucene搜索引擎 services.AddHttpClient("", c => c.Timeout = TimeSpan.FromSeconds(30)).ConfigurePrimaryHttpMessageHandler(provider => new HttpClientHandler { ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator }); //注入HttpClient services.AddHttpClient(); services.AddHttpContextAccessor(); //注入静态HttpContext services.AddMiniProfiler(options => { options.RouteBasePath = "/profiler"; options.EnableServerTimingHeader = true; options.ResultsAuthorize = req => req.HttpContext.Session.Get(SessionKey.UserInfo)?.IsAdmin ?? false; options.ResultsListAuthorize = options.ResultsAuthorize; options.IgnoredPaths.AddRange("/Assets/", "/Content/", "/fonts/", "/images/", "/ng-views/", "/Scripts/", "/static/", "/template/", "/cloud10.png", "/favicon.ico"); options.PopupRenderPosition = RenderPosition.BottomLeft; options.PopupShowTimeWithChildren = true; options.PopupShowTrivial = true; }).AddEntityFramework(); services.AddBundling().UseDefaults(_env).UseNUglify().EnableMinification().EnableChangeDetection().EnableCacheHeader(TimeSpan.FromHours(1)); switch (Configuration["MailSender"]) { case "Mailgun": services.AddHttpClient(); break; default: services.AddSingleton(); break; } services.AddMapper().AddAutofac().AddMyMvc().Configure(options => // X-Forwarded-For { options.ForwardLimit = null; options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; options.KnownNetworks.Clear(); options.KnownProxies.Clear(); }); } public void ConfigureContainer(ContainerBuilder builder) { builder.RegisterModule(new AutofacModule()); } /// /// Configure /// /// /// /// /// /// public void Configure(IApplicationBuilder app, IWebHostEnvironment env, DataContext db, IHangfireBackJob hangfire, LuceneIndexerOptions luceneIndexerOptions) { ServiceProvider = app.ApplicationServices; app.UseForwardedHeaders().UseCertificateForwarding(); // X-Forwarded-For if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/ServiceUnavailable"); } db.Database.EnsureCreated(); InitSettings(db); app.UseBundles(); UseLuceneSearch(env, hangfire, luceneIndexerOptions); if (bool.Parse(Configuration["Https:Enabled"])) { app.UseHttpsRedirection(); } switch (Configuration["UseRewriter"]) { case "NonWww": app.UseRewriter(new RewriteOptions().AddRedirectToNonWww()); // URL重写 break; case "WWW": app.UseRewriter(new RewriteOptions().AddRedirectToWww(301)); // URL重写 break; } app.UseDefaultFiles().UseStaticFiles(new StaticFileOptions //静态资源缓存策略 { OnPrepareResponse = context => { context.Context.Response.Headers[HeaderNames.CacheControl] = "public,no-cache"; context.Context.Response.Headers[HeaderNames.Expires] = DateTime.Now.AddDays(7).ToString("R"); }, ContentTypeProvider = new FileExtensionContentTypeProvider(MimeMapper.MimeTypes), }); app.UseSession().UseCookiePolicy().UseMiniProfiler(); //注入Session app.UseRequestIntercept(); //启用网站请求拦截 app.UseHangfireServer().UseHangfireDashboard("/taskcenter", new DashboardOptions() { Authorization = new[] { new MyRestrictiveAuthorizationFilter() } }); //配置hangfire app.UseResponseCaching().UseResponseCompression(); //启动Response缓存 app.UseActivity();// 抽奖活动 app.UseRouting(); // 放在 UseStaticFiles 之后 app.UseEndpoints(endpoints => { endpoints.MapControllers(); // 属性路由 endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}"); // 默认路由 endpoints.MapHub("/hubs"); }); HangfireJobInit.Start(); //初始化定时任务 Console.WriteLine("网站启动完成"); } private static void InitSettings(DataContext db) { var dic = db.SystemSetting.ToDictionary(s => s.Name, s => s.Value); //初始化系统设置参数 foreach (var (key, value) in dic) { CommonHelper.SystemSettings.TryAdd(key, value); } } private static void UseLuceneSearch(IHostEnvironment env, IHangfireBackJob hangfire, LuceneIndexerOptions luceneIndexerOptions) { Task.Run(() => { Console.WriteLine("正在导入自定义词库..."); double time = HiPerfTimer.Execute(() => { var lines = File.ReadAllLines(Path.Combine(env.ContentRootPath, "App_Data", "CustomKeywords.txt")); var segmenter = new JiebaSegmenter(); foreach (var word in lines) { segmenter.AddWord(word); } }); Console.WriteLine($"导入自定义词库完成,耗时{time}s"); }); string lucenePath = Path.Combine(env.ContentRootPath, luceneIndexerOptions.Path); if (!Directory.Exists(lucenePath) || Directory.GetFiles(lucenePath).Length < 1) { Console.WriteLine("索引库不存在,开始自动创建Lucene索引库..."); hangfire.CreateLuceneIndex(); Console.WriteLine("索引库创建完成!"); } } } /// /// hangfire授权拦截器 /// public class MyRestrictiveAuthorizationFilter : IDashboardAuthorizationFilter { /// /// 授权校验 /// /// /// public bool Authorize(DashboardContext context) { #if DEBUG return true; #endif var user = context.GetHttpContext().Session.Get(SessionKey.UserInfo) ?? new UserInfoDto(); return user.IsAdmin; } } }