Browse Source

修正编译报错

懒得勤快 2 years ago
parent
commit
47f15171d3

+ 1 - 1
src/Masuit.MyBlogs.Core/Controllers/AdvertisementController.cs

@@ -2,7 +2,6 @@
 using Dispose.Scope;
 using Masuit.MyBlogs.Core.Common;
 using Masuit.MyBlogs.Core.Extensions;
-using Masuit.Tools.AspNetCore.Mime;
 using Masuit.Tools.AspNetCore.ModelBinder;
 using Masuit.Tools.AspNetCore.ResumeFileResults.Extensions;
 using Masuit.Tools.Excel;
@@ -13,6 +12,7 @@ using Microsoft.Net.Http.Headers;
 using System.ComponentModel.DataAnnotations;
 using System.Net;
 using System.Text.RegularExpressions;
+using Masuit.Tools.Mime;
 
 namespace Masuit.MyBlogs.Core.Controllers;
 

+ 2 - 2
src/Masuit.MyBlogs.Core/Controllers/ErrorController.cs

@@ -4,7 +4,7 @@ using Masuit.MyBlogs.Core.Common;
 using Masuit.MyBlogs.Core.Common.Mails;
 using Masuit.MyBlogs.Core.Configs;
 using Masuit.MyBlogs.Core.Extensions.Firewall;
-using Masuit.Tools.AspNetCore.Mime;
+using Masuit.Tools.Mime;
 using Masuit.Tools.Core.Validator;
 using Masuit.Tools.Logging;
 using Microsoft.AspNetCore.Diagnostics;
@@ -224,4 +224,4 @@ public sealed class ErrorController : Controller
             Data = data
         });
     }
-}
+}

+ 166 - 160
src/Masuit.MyBlogs.Core/Controllers/FirewallController.cs

@@ -3,7 +3,7 @@ using FreeRedis;
 using Masuit.MyBlogs.Core.Common;
 using Masuit.MyBlogs.Core.Configs;
 using Masuit.MyBlogs.Core.Extensions.Firewall;
-using Masuit.Tools.AspNetCore.Mime;
+using Masuit.Tools.Mime;
 using Masuit.Tools.AspNetCore.ResumeFileResults.Extensions;
 using Microsoft.AspNetCore.Http.Extensions;
 using Microsoft.AspNetCore.Mvc;
@@ -15,167 +15,173 @@ namespace Masuit.MyBlogs.Core.Controllers;
 
 public sealed class FirewallController : Controller
 {
-	public IRedisClient RedisClient { get; set; }
-	private readonly HttpClient _httpClient;
-
-	public FirewallController(IHttpClientFactory httpClientFactory)
-	{
-		_httpClient = httpClientFactory.CreateClient();
-	}
-
-	/// <summary>
-	/// JS挑战,5秒盾
-	/// </summary>
-	/// <param name="token"></param>
-	/// <returns></returns>
-	[HttpPost("/challenge"), AutoValidateAntiforgeryToken]
-	public ActionResult JsChallenge()
-	{
-		try
-		{
-			HttpContext.Session.Set("js-challenge", 1);
-			Response.Cookies.Append(SessionKey.ChallengeBypass, DateTime.Now.AddSeconds(new Random().Next(60, 86400)).ToString("yyyy-MM-dd HH:mm:ss").AESEncrypt(AppConfig.BaiduAK), new CookieOptions()
-			{
-				SameSite = SameSiteMode.Lax,
-				Expires = DateTime.Now.AddDays(1)
-			});
-			return Ok();
-		}
-		catch
-		{
-			return BadRequest();
-		}
-	}
-
-	/// <summary>
-	/// 验证码
-	/// </summary>
-	/// <returns></returns>
-	[HttpGet("/challenge-captcha.jpg")]
-	[ResponseCache(NoStore = true, Duration = 0)]
-	public ActionResult CaptchaChallenge()
-	{
-		string code = ValidateCode.CreateValidateCode(6);
-		HttpContext.Session.Set("challenge-captcha", code);
-		var buffer = HttpContext.CreateValidateGraphic(code);
-		return this.ResumeFile(buffer, ContentType.Jpeg, "验证码.jpg");
-	}
-
-	/// <summary>
-	/// 验证码挑战
-	/// </summary>
-	/// <param name="code"></param>
-	/// <returns></returns>
-	[HttpPost("/captcha"), AutoValidateAntiforgeryToken]
-	public ActionResult CaptchaChallenge(string code)
-	{
-		if (string.IsNullOrEmpty(code) || code.Length < 4)
-		{
-			return BadRequest("验证码无效");
-		}
-
-		if (code.Equals(HttpContext.Session.Get<string>("challenge-captcha"), StringComparison.CurrentCultureIgnoreCase))
-		{
-			HttpContext.Session.Set("js-challenge", 1);
-			HttpContext.Session.Remove("challenge-captcha");
-			Response.Cookies.Append(SessionKey.ChallengeBypass, DateTime.Now.AddSeconds(new Random().Next(60, 86400)).ToString("yyyy-MM-dd HH:mm:ss").AESEncrypt(AppConfig.BaiduAK), new CookieOptions()
-			{
-				SameSite = SameSiteMode.Lax,
-				Expires = DateTime.Now.AddDays(1)
-			});
-		}
-
-		return Redirect(Request.Headers[HeaderNames.Referer]);
-	}
-
-	/// <summary>
-	/// CloudflareTurnstile验证
-	/// </summary>
-	/// <returns></returns>
-	[HttpPost("/turnstile-handler"), AutoValidateAntiforgeryToken]
-	public async Task<ActionResult> CloudflareTurnstileHandler()
-	{
-		var form = await Request.ReadFormAsync();
-		if (form.ContainsKey("cf-turnstile-response"))
-		{
-			var token = form["cf-turnstile-response"][0];
-			const string url = "https://challenges.cloudflare.com/turnstile/v0/siteverify";
-			using var encodedContent = new FormUrlEncodedContent(new List<KeyValuePair<string, string>>
-			{
-				new("secret",CommonHelper.SystemSettings["TurnstileSecretKey"]),
-				new("response",token),
-				new("remoteip",HttpContext.Connection.RemoteIpAddress.ToString()),
-			});
-			var resp = await _httpClient.PostAsync(url, encodedContent);
-			var result = await resp.Content.ReadFromJsonAsync<TurnstileResult>();
-			if (result.Success)
-			{
-				HttpContext.Session.Set("js-challenge", 1);
-				Response.Cookies.Append(SessionKey.ChallengeBypass, DateTime.Now.AddSeconds(new Random().Next(60, 86400)).ToString("yyyy-MM-dd HH:mm:ss").AESEncrypt(AppConfig.BaiduAK), new CookieOptions()
-				{
-					SameSite = SameSiteMode.Lax,
-					Expires = DateTime.Now.AddDays(1)
-				});
-			}
-		}
-
-		return Redirect(Request.Headers[HeaderNames.Referer]);
-	}
-
-	/// <summary>
-	/// 反爬虫检测
-	/// </summary>
-	/// <param name="id"></param>
-	/// <param name="cacheManager"></param>
-	/// <param name="env"></param>
-	/// <returns></returns>
-	[HttpGet("/craw/{id}")]
-	[ServiceFilter(typeof(FirewallAttribute))]
-	public IActionResult AntiCrawler(string id, [FromServices] ICacheManager<int> cacheManager, [FromServices] IWebHostEnvironment env)
-	{
-		if (Request.IsRobot())
-		{
-			return Ok();
-		}
-
-		var ip = HttpContext.Connection.RemoteIpAddress.ToString();
-		RedisClient.LPush("intercept", new IpIntercepter()
-		{
-			IP = ip,
-			RequestUrl = Request.GetDisplayUrl(),
-			Time = DateTime.Now,
-			Referer = Request.Headers[HeaderNames.Referer],
-			UserAgent = Request.Headers[HeaderNames.UserAgent],
-			Remark = "检测到异常爬虫行为",
-			Address = Request.Location(),
-			HttpVersion = Request.Protocol,
-			Headers = new
-			{
-				Request.Protocol,
-				Request.Headers
-			}.ToJsonString()
-		});
-		cacheManager.AddOrUpdate("AntiCrawler:" + ip, 1, i => i + 1, 5);
-		cacheManager.Expire("AntiCrawler:" + ip, ExpirationMode.Sliding, TimeSpan.FromMinutes(10));
-		if (cacheManager.Get<int>("AntiCrawler:" + ip) > 3)
-		{
-			Response.StatusCode = 429;
-			return Content("");
-		}
-
-		var sitemap = Path.Combine(env.WebRootPath, "sitemap.txt");
-		return System.IO.File.Exists(sitemap) ? Redirect(System.IO.File.ReadLines(sitemap).OrderByRandom().FirstOrDefault() ?? "/") : Redirect("/");
-	}
+    public IRedisClient RedisClient { get; set; }
+
+    private readonly HttpClient _httpClient;
+
+    public FirewallController(IHttpClientFactory httpClientFactory)
+    {
+        _httpClient = httpClientFactory.CreateClient();
+    }
+
+    /// <summary>
+    /// JS挑战,5秒盾
+    /// </summary>
+    /// <param name="token"></param>
+    /// <returns></returns>
+    [HttpPost("/challenge"), AutoValidateAntiforgeryToken]
+    public ActionResult JsChallenge()
+    {
+        try
+        {
+            HttpContext.Session.Set("js-challenge", 1);
+            Response.Cookies.Append(SessionKey.ChallengeBypass, DateTime.Now.AddSeconds(new Random().Next(60, 86400)).ToString("yyyy-MM-dd HH:mm:ss").AESEncrypt(AppConfig.BaiduAK), new CookieOptions()
+            {
+                SameSite = SameSiteMode.Lax,
+                Expires = DateTime.Now.AddDays(1)
+            });
+            return Ok();
+        }
+        catch
+        {
+            return BadRequest();
+        }
+    }
+
+    /// <summary>
+    /// 验证码
+    /// </summary>
+    /// <returns></returns>
+    [HttpGet("/challenge-captcha.jpg")]
+    [ResponseCache(NoStore = true, Duration = 0)]
+    public ActionResult CaptchaChallenge()
+    {
+        string code = ValidateCode.CreateValidateCode(6);
+        HttpContext.Session.Set("challenge-captcha", code);
+        using var buffer = code.CreateValidateGraphic();
+        return this.ResumeFile(buffer, ContentType.Jpeg, "验证码.jpg");
+    }
+
+    /// <summary>
+    /// 验证码挑战
+    /// </summary>
+    /// <param name="code"></param>
+    /// <returns></returns>
+    [HttpPost("/captcha"), AutoValidateAntiforgeryToken]
+    public ActionResult CaptchaChallenge(string code)
+    {
+        if (string.IsNullOrEmpty(code) || code.Length < 4)
+        {
+            return BadRequest("验证码无效");
+        }
+
+        if (code.Equals(HttpContext.Session.Get<string>("challenge-captcha"), StringComparison.CurrentCultureIgnoreCase))
+        {
+            HttpContext.Session.Set("js-challenge", 1);
+            HttpContext.Session.Remove("challenge-captcha");
+            Response.Cookies.Append(SessionKey.ChallengeBypass, DateTime.Now.AddSeconds(new Random().Next(60, 86400)).ToString("yyyy-MM-dd HH:mm:ss").AESEncrypt(AppConfig.BaiduAK), new CookieOptions()
+            {
+                SameSite = SameSiteMode.Lax,
+                Expires = DateTime.Now.AddDays(1)
+            });
+        }
+
+        return Redirect(Request.Headers[HeaderNames.Referer]);
+    }
+
+    /// <summary>
+    /// CloudflareTurnstile验证
+    /// </summary>
+    /// <returns></returns>
+    [HttpPost("/turnstile-handler"), AutoValidateAntiforgeryToken]
+    public async Task<ActionResult> CloudflareTurnstileHandler()
+    {
+        var form = await Request.ReadFormAsync();
+        if (form.ContainsKey("cf-turnstile-response"))
+        {
+            var token = form["cf-turnstile-response"][0];
+            const string url = "https://challenges.cloudflare.com/turnstile/v0/siteverify";
+            using var encodedContent = new FormUrlEncodedContent(new List<KeyValuePair<string, string>>
+            {
+                new("secret",CommonHelper.SystemSettings["TurnstileSecretKey"]),
+                new("response",token),
+                new("remoteip",HttpContext.Connection.RemoteIpAddress.ToString()),
+            });
+            var resp = await _httpClient.PostAsync(url, encodedContent);
+            var result = await resp.Content.ReadFromJsonAsync<TurnstileResult>();
+            if (result.Success)
+            {
+                HttpContext.Session.Set("js-challenge", 1);
+                Response.Cookies.Append(SessionKey.ChallengeBypass, DateTime.Now.AddSeconds(new Random().Next(60, 86400)).ToString("yyyy-MM-dd HH:mm:ss").AESEncrypt(AppConfig.BaiduAK), new CookieOptions()
+                {
+                    SameSite = SameSiteMode.Lax,
+                    Expires = DateTime.Now.AddDays(1)
+                });
+            }
+        }
+
+        return Redirect(Request.Headers[HeaderNames.Referer]);
+    }
+
+    /// <summary>
+    /// 反爬虫检测
+    /// </summary>
+    /// <param name="id"></param>
+    /// <param name="cacheManager"></param>
+    /// <param name="env"></param>
+    /// <returns></returns>
+    [HttpGet("/craw/{id}")]
+    [ServiceFilter(typeof(FirewallAttribute))]
+    public IActionResult AntiCrawler(string id, [FromServices] ICacheManager<int> cacheManager, [FromServices] IWebHostEnvironment env)
+    {
+        if (Request.IsRobot())
+        {
+            return Ok();
+        }
+
+        var ip = HttpContext.Connection.RemoteIpAddress.ToString();
+        RedisClient.LPush("intercept", new IpIntercepter()
+        {
+            IP = ip,
+            RequestUrl = Request.GetDisplayUrl(),
+            Time = DateTime.Now,
+            Referer = Request.Headers[HeaderNames.Referer],
+            UserAgent = Request.Headers[HeaderNames.UserAgent],
+            Remark = "检测到异常爬虫行为",
+            Address = Request.Location(),
+            HttpVersion = Request.Protocol,
+            Headers = new
+            {
+                Request.Protocol,
+                Request.Headers
+            }.ToJsonString()
+        });
+        cacheManager.AddOrUpdate("AntiCrawler:" + ip, 1, i => i + 1, 5);
+        cacheManager.Expire("AntiCrawler:" + ip, ExpirationMode.Sliding, TimeSpan.FromMinutes(10));
+        if (cacheManager.Get<int>("AntiCrawler:" + ip) > 3)
+        {
+            Response.StatusCode = 429;
+            return Content("");
+        }
+
+        var sitemap = Path.Combine(env.WebRootPath, "sitemap.txt");
+        return System.IO.File.Exists(sitemap) ? Redirect(System.IO.File.ReadLines(sitemap).OrderByRandom().FirstOrDefault() ?? "/") : Redirect("/");
+    }
 }
 
 public class TurnstileResult
 {
-	public bool Success { get; set; }
-	[JsonProperty("error-codes")]
-	public string[] ErrorCodes { get; set; }
-	[JsonProperty("challenge_ts")]
-	public DateTime ChallengeTime { get; set; }
-	public string Hostname { get; set; }
-	public string Action { get; set; }
-	public string Cdata { get; set; }
+    public bool Success { get; set; }
+
+    [JsonProperty("error-codes")]
+    public string[] ErrorCodes { get; set; }
+
+    [JsonProperty("challenge_ts")]
+    public DateTime ChallengeTime { get; set; }
+
+    public string Hostname { get; set; }
+
+    public string Action { get; set; }
+
+    public string Cdata { get; set; }
 }

+ 1 - 1
src/Masuit.MyBlogs.Core/Controllers/HomeController.cs

@@ -4,7 +4,7 @@ using Dispose.Scope;
 using Masuit.MyBlogs.Core.Common;
 using Masuit.MyBlogs.Core.Extensions;
 using Masuit.MyBlogs.Core.Models;
-using Masuit.Tools.AspNetCore.Mime;
+using Masuit.Tools.Mime;
 using Masuit.Tools.Models;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.EntityFrameworkCore;

+ 4 - 3
src/Masuit.MyBlogs.Core/Controllers/PassportController.cs

@@ -4,7 +4,7 @@ using Hangfire;
 using Masuit.MyBlogs.Core.Configs;
 using Masuit.MyBlogs.Core.Extensions.Firewall;
 using Masuit.MyBlogs.Core.Extensions.Hangfire;
-using Masuit.Tools.AspNetCore.Mime;
+using Masuit.Tools.Mime;
 using Masuit.Tools.AspNetCore.ResumeFileResults.Extensions;
 using Masuit.Tools.Logging;
 using Microsoft.AspNetCore.Mvc;
@@ -25,6 +25,7 @@ public sealed class PassportController : Controller
     public IUserInfoService UserInfoService { get; set; }
 
     public IFirewallRepoter FirewallRepoter { get; set; }
+
     public IMapper Mapper { get; set; }
 
     /// <summary>
@@ -194,7 +195,7 @@ public sealed class PassportController : Controller
     {
         string code = Tools.Strings.ValidateCode.CreateValidateCode(6);
         HttpContext.Session.Set("valid", code); //将验证码生成到Session中
-        var buffer = HttpContext.CreateValidateGraphic(code);
+        using var buffer = code.CreateValidateGraphic();
         return this.ResumeFile(buffer, ContentType.Jpeg, "验证码.jpg");
     }
 
@@ -247,4 +248,4 @@ public sealed class PassportController : Controller
         HttpContext.Session.Clear();
         return Request.Method.Equals(HttpMethods.Get) ? RedirectToAction("Index", "Home") : ResultData(null, message: "注销成功!");
     }
-}
+}

+ 1 - 1
src/Masuit.MyBlogs.Core/Controllers/PostController.cs

@@ -9,7 +9,6 @@ using Masuit.MyBlogs.Core.Configs;
 using Masuit.MyBlogs.Core.Extensions;
 using Masuit.MyBlogs.Core.Extensions.Firewall;
 using Masuit.MyBlogs.Core.Extensions.Hangfire;
-using Masuit.Tools.AspNetCore.Mime;
 using Masuit.Tools.AspNetCore.ModelBinder;
 using Masuit.Tools.AspNetCore.ResumeFileResults.Extensions;
 using Masuit.Tools.Core.Validator;
@@ -26,6 +25,7 @@ using System.Linq.Dynamic.Core;
 using System.Net;
 using System.Text;
 using System.Text.RegularExpressions;
+using Masuit.Tools.Mime;
 using Z.EntityFramework.Plus;
 using SameSiteMode = Microsoft.AspNetCore.Http.SameSiteMode;
 

+ 1 - 1
src/Masuit.MyBlogs.Core/Controllers/SubscribeController.cs

@@ -3,7 +3,7 @@ using FreeRedis;
 using Masuit.MyBlogs.Core.Common;
 using Masuit.MyBlogs.Core.Extensions;
 using Masuit.MyBlogs.Core.Extensions.Firewall;
-using Masuit.Tools.AspNetCore.Mime;
+using Masuit.Tools.Mime;
 using Masuit.Tools.Models;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.EntityFrameworkCore;

+ 1 - 1
src/Masuit.MyBlogs.Core/Controllers/ToolsController.cs

@@ -2,7 +2,7 @@
 using DnsClient;
 using Masuit.MyBlogs.Core.Common;
 using Masuit.MyBlogs.Core.Configs;
-using Masuit.Tools.AspNetCore.Mime;
+using Masuit.Tools.Mime;
 using Masuit.Tools.Core.Validator;
 using Masuit.Tools.Models;
 using MaxMind.GeoIP2.Exceptions;

+ 1 - 1
src/Masuit.MyBlogs.Core/Controllers/UploadController.cs

@@ -3,7 +3,6 @@ using DocumentFormat.OpenXml.Packaging;
 using Masuit.MyBlogs.Core.Common;
 using Masuit.MyBlogs.Core.Extensions.Firewall;
 using Masuit.MyBlogs.Core.Extensions.UEditor;
-using Masuit.Tools.AspNetCore.Mime;
 using Masuit.Tools.AspNetCore.ResumeFileResults.Extensions;
 using Masuit.Tools.Html;
 using Masuit.Tools.Logging;
@@ -14,6 +13,7 @@ using System.ComponentModel.DataAnnotations;
 using System.Diagnostics;
 using System.Text.RegularExpressions;
 using System.Xml.Linq;
+using Masuit.Tools.Mime;
 using Configuration = AngleSharp.Configuration;
 
 namespace Masuit.MyBlogs.Core.Controllers;

+ 212 - 211
src/Masuit.MyBlogs.Core/Extensions/Firewall/FirewallAttribute.cs

@@ -4,7 +4,7 @@ using Markdig;
 using Masuit.MyBlogs.Core.Common;
 using Masuit.MyBlogs.Core.Configs;
 using Masuit.MyBlogs.Core.Controllers;
-using Masuit.Tools.AspNetCore.Mime;
+using Masuit.Tools.Mime;
 using Masuit.Tools.Logging;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.AspNetCore.Mvc.Filters;
@@ -20,239 +20,240 @@ namespace Masuit.MyBlogs.Core.Extensions.Firewall;
 
 public sealed class FirewallAttribute : IAsyncActionFilter
 {
-	public ICacheManager<int> CacheManager { get; set; }
+    public ICacheManager<int> CacheManager { get; set; }
 
-	public IFirewallRepoter FirewallRepoter { get; set; }
+    public IFirewallRepoter FirewallRepoter { get; set; }
 
-	public IMemoryCache MemoryCache { get; set; }
-	public IRedisClient RedisClient { get; set; }
+    public IMemoryCache MemoryCache { get; set; }
 
-	public Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
-	{
-		var request = context.HttpContext.Request;
-		if (CommonHelper.SystemSettings.TryGetValue("BlockHeaderValues", out var v) && v.Length > 0)
-		{
-			var strs = v.Split("|", StringSplitOptions.RemoveEmptyEntries);
-			if (request.Headers.Values.Any(values => strs.Any(s => values.Contains(s))))
-			{
-				context.Result = new NotFoundResult();
-				return Task.CompletedTask;
-			}
-		}
+    public IRedisClient RedisClient { get; set; }
 
-		request.Headers.Values.Contains("");
-		var ip = context.HttpContext.Connection.RemoteIpAddress.ToString();
-		var tokenValid = request.Cookies.ContainsKey("FullAccessToken") && request.Cookies["Email"].MDString(AppConfig.BaiduAK).Equals(request.Cookies["FullAccessToken"]);
+    public Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
+    {
+        var request = context.HttpContext.Request;
+        if (CommonHelper.SystemSettings.TryGetValue("BlockHeaderValues", out var v) && v.Length > 0)
+        {
+            var strs = v.Split("|", StringSplitOptions.RemoveEmptyEntries);
+            if (request.Headers.Values.Any(values => strs.Any(s => values.Contains(s))))
+            {
+                context.Result = new NotFoundResult();
+                return Task.CompletedTask;
+            }
+        }
 
-		//黑名单
-		if (ip.IsDenyIpAddress() && !tokenValid)
-		{
-			AccessDeny(ip, request, "黑名单IP地址");
-			context.Result = new BadRequestObjectResult("您当前所在的网络环境不支持访问本站!");
-			return Task.CompletedTask;
-		}
+        request.Headers.Values.Contains("");
+        var ip = context.HttpContext.Connection.RemoteIpAddress.ToString();
+        var tokenValid = request.Cookies.ContainsKey("FullAccessToken") && request.Cookies["Email"].MDString(AppConfig.BaiduAK).Equals(request.Cookies["FullAccessToken"]);
 
-		//bypass
-		if (CommonHelper.SystemSettings.GetOrAdd("FirewallEnabled", "true") == "false" || context.ActionDescriptor.EndpointMetadata.Any(o => o is MyAuthorizeAttribute or AllowAccessFirewallAttribute) || tokenValid)
-		{
-			return next();
-		}
+        //黑名单
+        if (ip.IsDenyIpAddress() && !tokenValid)
+        {
+            AccessDeny(ip, request, "黑名单IP地址");
+            context.Result = new BadRequestObjectResult("您当前所在的网络环境不支持访问本站!");
+            return Task.CompletedTask;
+        }
 
-		//UserAgent
-		var ua = request.Headers[HeaderNames.UserAgent] + "";
-		var blocked = CommonHelper.SystemSettings.GetOrAdd("UserAgentBlocked", "").Split(new[]
-		{
-			',',
-			'|'
-		}, StringSplitOptions.RemoveEmptyEntries);
-		if (ua.Contains(blocked))
-		{
-			var agent = UserAgent.Parse(ua);
-			AccessDeny(ip, request, $"UA黑名单({agent.Browser} {agent.BrowserVersion}/{agent.Platform})");
-			var msg = CommonHelper.SystemSettings.GetOrAdd("UserAgentBlockedMsg", "当前浏览器不支持访问本站");
-			context.Result = new ContentResult
-			{
-				Content = Markdown.ToHtml(Template.Create(msg).Set("browser", agent.Browser + " " + agent.BrowserVersion).Set("os", agent.Platform).Render()),
-				ContentType = ContentType.Html + "; charset=utf-8",
-				StatusCode = 403
-			};
-			return Task.CompletedTask;
-		}
+        //bypass
+        if (CommonHelper.SystemSettings.GetOrAdd("FirewallEnabled", "true") == "false" || context.ActionDescriptor.EndpointMetadata.Any(o => o is MyAuthorizeAttribute or AllowAccessFirewallAttribute) || tokenValid)
+        {
+            return next();
+        }
 
-		//搜索引擎
-		if (Regex.IsMatch(request.Method, "OPTIONS|HEAD", RegexOptions.IgnoreCase) || request.IsRobot())
-		{
-			return next();
-		}
+        //UserAgent
+        var ua = request.Headers[HeaderNames.UserAgent] + "";
+        var blocked = CommonHelper.SystemSettings.GetOrAdd("UserAgentBlocked", "").Split(new[]
+        {
+            ',',
+            '|'
+        }, StringSplitOptions.RemoveEmptyEntries);
+        if (ua.Contains(blocked))
+        {
+            var agent = UserAgent.Parse(ua);
+            AccessDeny(ip, request, $"UA黑名单({agent.Browser} {agent.BrowserVersion}/{agent.Platform})");
+            var msg = CommonHelper.SystemSettings.GetOrAdd("UserAgentBlockedMsg", "当前浏览器不支持访问本站");
+            context.Result = new ContentResult
+            {
+                Content = Markdown.ToHtml(Template.Create(msg).Set("browser", agent.Browser + " " + agent.BrowserVersion).Set("os", agent.Platform).Render()),
+                ContentType = ContentType.Html + "; charset=utf-8",
+                StatusCode = 403
+            };
+            return Task.CompletedTask;
+        }
 
-		// 反爬虫
-		if (CacheManager.GetOrAdd(nameof(FirewallController.AntiCrawler) + ":" + ip, 0) > 3)
-		{
-			context.Result = new ContentResult
-			{
-				ContentType = ContentType.Html + "; charset=utf-8",
-				StatusCode = 429,
-				Content = "检测到访问异常,请在10分钟后再试!"
-			};
-			return Task.CompletedTask;
-		}
+        //搜索引擎
+        if (Regex.IsMatch(request.Method, "OPTIONS|HEAD", RegexOptions.IgnoreCase) || request.IsRobot())
+        {
+            return next();
+        }
 
-		//安全模式
-		if (request.Query[SessionKey.SafeMode].Count > 0)
-		{
-			request.Cookies.TryGetValue(SessionKey.HideCategories, out var s);
-			context.HttpContext.Response.Cookies.Append(SessionKey.HideCategories, request.Query[SessionKey.SafeMode] + "," + s, new CookieOptions
-			{
-				Expires = DateTime.Now.AddYears(1),
-				SameSite = SameSiteMode.Lax
-			});
-		}
+        // 反爬虫
+        if (CacheManager.GetOrAdd(nameof(FirewallController.AntiCrawler) + ":" + ip, 0) > 3)
+        {
+            context.Result = new ContentResult
+            {
+                ContentType = ContentType.Html + "; charset=utf-8",
+                StatusCode = 429,
+                Content = "检测到访问异常,请在10分钟后再试!"
+            };
+            return Task.CompletedTask;
+        }
 
-		//白名单地区
-		var ipLocation = context.HttpContext.Connection.RemoteIpAddress.GetIPLocation();
-		var (location, network, pos) = ipLocation;
-		pos += ipLocation.Coodinate;
-		var allowedAreas = CommonHelper.SystemSettings.GetOrAdd("AllowedArea", "").Split(new[]
-		{
-			',',
-			','
-		}, StringSplitOptions.RemoveEmptyEntries);
-		if (allowedAreas.Any() && pos.Contains(allowedAreas))
-		{
-			return next();
-		}
+        //安全模式
+        if (request.Query[SessionKey.SafeMode].Count > 0)
+        {
+            request.Cookies.TryGetValue(SessionKey.HideCategories, out var s);
+            context.HttpContext.Response.Cookies.Append(SessionKey.HideCategories, request.Query[SessionKey.SafeMode] + "," + s, new CookieOptions
+            {
+                Expires = DateTime.Now.AddYears(1),
+                SameSite = SameSiteMode.Lax
+            });
+        }
 
-		//黑名单地区
-		var denyAreas = CommonHelper.SystemSettings.GetOrAdd("DenyArea", "").Split(new[] { ',', ',' }, StringSplitOptions.RemoveEmptyEntries);
-		if (denyAreas.Any())
-		{
-			if (string.IsNullOrWhiteSpace(location) || string.IsNullOrWhiteSpace(network) || pos.Contains(denyAreas) || denyAreas.Intersect(pos.Split("|")).Any()) // 未知地区的,未知网络的,禁区的
-			{
-				AccessDeny(ip, request, "访问地区限制");
-				throw new AccessDenyException("访问地区限制");
-			}
-		}
+        //白名单地区
+        var ipLocation = context.HttpContext.Connection.RemoteIpAddress.GetIPLocation();
+        var (location, network, pos) = ipLocation;
+        pos += ipLocation.Coodinate;
+        var allowedAreas = CommonHelper.SystemSettings.GetOrAdd("AllowedArea", "").Split(new[]
+        {
+            ',',
+            ','
+        }, StringSplitOptions.RemoveEmptyEntries);
+        if (allowedAreas.Any() && pos.Contains(allowedAreas))
+        {
+            return next();
+        }
 
-		//挑战模式
-		if (context.HttpContext.Session.TryGetValue("js-challenge", out _) || request.Path.ToUriComponent().Contains("."))
-		{
-			return next();
-		}
+        //黑名单地区
+        var denyAreas = CommonHelper.SystemSettings.GetOrAdd("DenyArea", "").Split(new[] { ',', ',' }, StringSplitOptions.RemoveEmptyEntries);
+        if (denyAreas.Any())
+        {
+            if (string.IsNullOrWhiteSpace(location) || string.IsNullOrWhiteSpace(network) || pos.Contains(denyAreas) || denyAreas.Intersect(pos.Split("|")).Any()) // 未知地区的,未知网络的,禁区的
+            {
+                AccessDeny(ip, request, "访问地区限制");
+                throw new AccessDenyException("访问地区限制");
+            }
+        }
 
-		try
-		{
-			if (request.Cookies.TryGetValue(SessionKey.ChallengeBypass, out var time) && time.AESDecrypt(AppConfig.BaiduAK).ToDateTime() > DateTime.Now)
-			{
-				context.HttpContext.Session.Set("js-challenge", 1);
-				return next();
-			}
-		}
-		catch
-		{
-			context.HttpContext.Response.Cookies.Delete(SessionKey.ChallengeBypass);
-		}
+        //挑战模式
+        if (context.HttpContext.Session.TryGetValue("js-challenge", out _) || request.Path.ToUriComponent().Contains("."))
+        {
+            return next();
+        }
 
-		if (Challenge(context, out var completedTask))
-		{
-			return completedTask;
-		}
+        try
+        {
+            if (request.Cookies.TryGetValue(SessionKey.ChallengeBypass, out var time) && time.AESDecrypt(AppConfig.BaiduAK).ToDateTime() > DateTime.Now)
+            {
+                context.HttpContext.Session.Set("js-challenge", 1);
+                return next();
+            }
+        }
+        catch
+        {
+            context.HttpContext.Response.Cookies.Delete(SessionKey.ChallengeBypass);
+        }
 
-		//限流
-		return ThrottleLimit(ip, request, next);
-	}
+        if (Challenge(context, out var completedTask))
+        {
+            return completedTask;
+        }
 
-	private static bool Challenge(ActionExecutingContext context, out Task completedTask)
-	{
+        //限流
+        return ThrottleLimit(ip, request, next);
+    }
+
+    private static bool Challenge(ActionExecutingContext context, out Task completedTask)
+    {
 #if DEBUG
-		completedTask = Task.CompletedTask;
-		return false;
+        completedTask = Task.CompletedTask;
+        return false;
 #endif
-		var mode = CommonHelper.SystemSettings.GetOrAdd(SessionKey.ChallengeMode, "");
-		if (mode == SessionKey.JSChallenge)
-		{
-			context.Result = new ViewResult
-			{
-				ViewName = "/Views/Shared/JSChallenge.cshtml"
-			};
-			completedTask = Task.CompletedTask;
-			return true;
-		}
+        var mode = CommonHelper.SystemSettings.GetOrAdd(SessionKey.ChallengeMode, "");
+        if (mode == SessionKey.JSChallenge)
+        {
+            context.Result = new ViewResult
+            {
+                ViewName = "/Views/Shared/JSChallenge.cshtml"
+            };
+            completedTask = Task.CompletedTask;
+            return true;
+        }
 
-		if (mode == SessionKey.CaptchaChallenge)
-		{
-			context.Result = new ViewResult
-			{
-				ViewName = "/Views/Shared/CaptchaChallenge.cshtml"
-			};
-			completedTask = Task.CompletedTask;
-			return true;
-		}
+        if (mode == SessionKey.CaptchaChallenge)
+        {
+            context.Result = new ViewResult
+            {
+                ViewName = "/Views/Shared/CaptchaChallenge.cshtml"
+            };
+            completedTask = Task.CompletedTask;
+            return true;
+        }
 
-		if (mode == SessionKey.CloudflareTurnstileChallenge)
-		{
-			context.Result = new ViewResult
-			{
-				ViewName = "/Views/Shared/CloudflareTurnstileChallenge.cshtml"
-			};
-			completedTask = Task.CompletedTask;
-			return true;
-		}
+        if (mode == SessionKey.CloudflareTurnstileChallenge)
+        {
+            context.Result = new ViewResult
+            {
+                ViewName = "/Views/Shared/CloudflareTurnstileChallenge.cshtml"
+            };
+            completedTask = Task.CompletedTask;
+            return true;
+        }
 
-		completedTask = Task.CompletedTask;
-		return false;
-	}
+        completedTask = Task.CompletedTask;
+        return false;
+    }
 
-	private Task ThrottleLimit(string ip, HttpRequest request, ActionExecutionDelegate next)
-	{
-		var times = CacheManager.AddOrUpdate("Frequency:" + ip, 1, i => i + 1, 5);
-		CacheManager.Expire("Frequency:" + ip, ExpirationMode.Absolute, TimeSpan.FromSeconds(CommonHelper.SystemSettings.GetOrAdd("LimitIPFrequency", "60").ToInt32()));
-		var limit = CommonHelper.SystemSettings.GetOrAdd("LimitIPRequestTimes", "90").ToInt32();
-		if (times <= limit)
-		{
-			return next();
-		}
+    private Task ThrottleLimit(string ip, HttpRequest request, ActionExecutionDelegate next)
+    {
+        var times = CacheManager.AddOrUpdate("Frequency:" + ip, 1, i => i + 1, 5);
+        CacheManager.Expire("Frequency:" + ip, ExpirationMode.Absolute, TimeSpan.FromSeconds(CommonHelper.SystemSettings.GetOrAdd("LimitIPFrequency", "60").ToInt32()));
+        var limit = CommonHelper.SystemSettings.GetOrAdd("LimitIPRequestTimes", "90").ToInt32();
+        if (times <= limit)
+        {
+            return next();
+        }
 
-		if (times > limit * 1.2)
-		{
-			CacheManager.Expire("Frequency:" + ip, TimeSpan.FromMinutes(CommonHelper.SystemSettings.GetOrAdd("BanIPTimespan", "10").ToInt32()));
-			AccessDeny(ip, request, "访问频次限制");
-			throw new TempDenyException("访问频次限制");
-		}
+        if (times > limit * 1.2)
+        {
+            CacheManager.Expire("Frequency:" + ip, TimeSpan.FromMinutes(CommonHelper.SystemSettings.GetOrAdd("BanIPTimespan", "10").ToInt32()));
+            AccessDeny(ip, request, "访问频次限制");
+            throw new TempDenyException("访问频次限制");
+        }
 
-		return next();
-	}
+        return next();
+    }
 
-	private async void AccessDeny(string ip, HttpRequest request, string remark)
-	{
-		var path = HttpUtility.UrlDecode(request.Path + request.QueryString, Encoding.UTF8);
-		RedisClient.IncrBy("interceptCount", 1);
-		RedisClient.LPush("intercept", new IpIntercepter
-		{
-			IP = ip,
-			RequestUrl = HttpUtility.UrlDecode(request.Scheme + "://" + request.Host + path),
-			Time = DateTime.Now,
-			Referer = request.Headers[HeaderNames.Referer],
-			UserAgent = request.Headers[HeaderNames.UserAgent],
-			Remark = remark,
-			Address = request.Location(),
-			HttpVersion = request.Protocol,
-			Headers = new
-			{
-				request.Protocol,
-				request.Headers
-			}.ToJsonString()
-		});
-		var limit = CommonHelper.SystemSettings.GetOrAdd("LimitIPInterceptTimes", "30").ToInt32();
-		var list = RedisClient.LRange<IpIntercepter>("intercept", 0, -1);
-		var key = "FirewallRepoter:" + FirewallRepoter.ReporterName + ":" + ip;
-		if (list.Count(x => x.IP == ip) >= limit && !MemoryCache.TryGetValue(key, out _))
-		{
-			LogManager.Info($"准备上报IP{ip}到{FirewallRepoter.ReporterName}");
-			await FirewallRepoter.ReportAsync(IPAddress.Parse(ip)).ContinueWith(_ =>
-			{
-				MemoryCache.Set(key, 1, TimeSpan.FromDays(1));
-				LogManager.Info($"访问频次限制,已上报IP{ip}至:" + FirewallRepoter.ReporterName);
-			});
-		}
-	}
-}
+    private async void AccessDeny(string ip, HttpRequest request, string remark)
+    {
+        var path = HttpUtility.UrlDecode(request.Path + request.QueryString, Encoding.UTF8);
+        RedisClient.IncrBy("interceptCount", 1);
+        RedisClient.LPush("intercept", new IpIntercepter
+        {
+            IP = ip,
+            RequestUrl = HttpUtility.UrlDecode(request.Scheme + "://" + request.Host + path),
+            Time = DateTime.Now,
+            Referer = request.Headers[HeaderNames.Referer],
+            UserAgent = request.Headers[HeaderNames.UserAgent],
+            Remark = remark,
+            Address = request.Location(),
+            HttpVersion = request.Protocol,
+            Headers = new
+            {
+                request.Protocol,
+                request.Headers
+            }.ToJsonString()
+        });
+        var limit = CommonHelper.SystemSettings.GetOrAdd("LimitIPInterceptTimes", "30").ToInt32();
+        var list = RedisClient.LRange<IpIntercepter>("intercept", 0, -1);
+        var key = "FirewallRepoter:" + FirewallRepoter.ReporterName + ":" + ip;
+        if (list.Count(x => x.IP == ip) >= limit && !MemoryCache.TryGetValue(key, out _))
+        {
+            LogManager.Info($"准备上报IP{ip}到{FirewallRepoter.ReporterName}");
+            await FirewallRepoter.ReportAsync(IPAddress.Parse(ip)).ContinueWith(_ =>
+            {
+                MemoryCache.Set(key, 1, TimeSpan.FromDays(1));
+                LogManager.Info($"访问频次限制,已上报IP{ip}至:" + FirewallRepoter.ReporterName);
+            });
+        }
+    }
+}

+ 1 - 1
src/Masuit.MyBlogs.Core/Extensions/MiddlewareExtension.cs

@@ -2,7 +2,7 @@
 using AutoMapper.Extensions.ExpressionMapping;
 using CacheManager.Core;
 using Masuit.MyBlogs.Core.Configs;
-using Masuit.Tools.AspNetCore.Mime;
+using Masuit.Tools.Mime;
 using Masuit.Tools.AspNetCore.ModelBinder;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.AspNetCore.Mvc.Filters;

+ 2 - 2
src/Masuit.MyBlogs.Core/Extensions/TranslateMiddleware.cs

@@ -1,5 +1,5 @@
 using Masuit.MyBlogs.Core.Common;
-using Masuit.Tools.AspNetCore.Mime;
+using Masuit.Tools.Mime;
 using Microsoft.International.Converters.TraditionalChineseToSimplifiedConverter;
 using System.Text;
 
@@ -76,4 +76,4 @@ public sealed class TranslateMiddleware
             await _next(context);
         }
     }
-}
+}

+ 3 - 3
src/Masuit.MyBlogs.Core/Extensions/UEditor/CrawlerHandler.cs

@@ -1,7 +1,6 @@
 using Masuit.MyBlogs.Core.Common;
-using Masuit.Tools.AspNetCore.Mime;
+using Masuit.Tools.Mime;
 using Masuit.Tools.Logging;
-using SixLabors.ImageSharp;
 using System.Diagnostics;
 using System.Net;
 using System.Text.RegularExpressions;
@@ -62,6 +61,7 @@ public class Crawler
     private readonly HttpClient _httpClient;
     private readonly IConfiguration _configuration;
     private readonly HttpContext _httpContext;
+
     public Crawler(string sourceUrl, HttpClient httpClient, IConfiguration configuration, HttpContext httpContext)
     {
         SourceUrl = sourceUrl;
@@ -128,4 +128,4 @@ public class Crawler
 
         return this;
     }
-}
+}

+ 6 - 6
src/Masuit.MyBlogs.Core/Masuit.MyBlogs.Core.csproj

@@ -49,10 +49,10 @@
         <PackageReference Include="CHTCHSConv" Version="1.0.0" />
         <PackageReference Include="CLRStats" Version="1.0.0" />
         <PackageReference Include="Dispose.Scope.AspNetCore" Version="0.0.3" />
-        <PackageReference Include="FreeRedis" Version="1.0.10" />
-        <PackageReference Include="Hangfire" Version="1.8.0" />
+        <PackageReference Include="FreeRedis" Version="1.1.0" />
+        <PackageReference Include="Hangfire" Version="1.8.2" />
         <PackageReference Include="Hangfire.MemoryStorage" Version="1.7.0" />
-        <PackageReference Include="htmldiff.net" Version="1.4.0" />
+        <PackageReference Include="htmldiff.net" Version="1.4.1" />
         <PackageReference Include="Karambolo.AspNetCore.Bundling.NUglify" Version="3.6.1" />
         <PackageReference Include="Markdig" Version="0.31.0" />
         <PackageReference Include="MaxMind.GeoIP2" Version="5.1.0" />
@@ -63,16 +63,16 @@
         <PackageReference Include="Microsoft.Graph" Version="4.54.0" />
         <PackageReference Include="Microsoft.Graph.Auth" Version="1.0.0-preview.7" />
         <PackageReference Include="Microsoft.NETCore.Platforms" Version="7.0.2" />
-        <PackageReference Include="MiniProfiler.AspNetCore.Mvc" Version="4.2.22" />
+        <PackageReference Include="MiniProfiler.AspNetCore.Mvc" Version="4.3.8" />
         <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.4" />
         <PackageReference Include="OpenXmlPowerTools-NetStandard" Version="4.6.23-alpha4" />
-        <PackageReference Include="MiniProfiler.EntityFrameworkCore" Version="4.2.22" />
+        <PackageReference Include="MiniProfiler.EntityFrameworkCore" Version="4.3.8" />
         <PackageReference Include="PanGu.HighLight" Version="1.0.0" />
         <PackageReference Include="SixLabors.ImageSharp.Web" Version="3.0.1" />
         <PackageReference Include="System.Linq.Dynamic.Core" Version="1.3.2" />
         <PackageReference Include="TimeZoneConverter" Version="6.1.0" />
         <PackageReference Include="WilderMinds.RssSyndication" Version="1.7.0" />
-        <PackageReference Include="Z.EntityFramework.Plus.EFCore" Version="7.21.0" />
+        <PackageReference Include="Z.EntityFramework.Plus.EFCore" Version="7.22.0" />
     </ItemGroup>
     <ItemGroup>
         <Content Update="appsettings.json">

+ 200 - 201
src/Masuit.MyBlogs.Core/PrepareStartup.cs

@@ -4,7 +4,7 @@ using Masuit.LuceneEFCore.SearchEngine;
 using Masuit.MyBlogs.Core.Common;
 using Masuit.MyBlogs.Core.Configs;
 using Masuit.MyBlogs.Core.Extensions.Hangfire;
-using Masuit.Tools.AspNetCore.Mime;
+using Masuit.Tools.Mime;
 using Masuit.Tools.Win32;
 using Microsoft.AspNetCore.Http.Features;
 using Microsoft.AspNetCore.HttpOverrides;
@@ -26,206 +26,205 @@ using SameSiteMode = Microsoft.AspNetCore.Http.SameSiteMode;
 
 namespace Masuit.MyBlogs.Core
 {
-	public static class PrepareStartup
-	{
-		/// <summary>
-		/// 初始化系统设置参数
-		/// </summary>
-		/// <param name="app"></param>
-		internal static void InitSettings(this IApplicationBuilder app)
-		{
-			var dic = app.ApplicationServices.GetRequiredService<DataContext>().SystemSetting.ToDictionary(s => s.Name, s => s.Value);
-			CommonHelper.SystemSettings.AddOrUpdate(dic);
-		}
-
-		internal static void UseLuceneSearch(this IApplicationBuilder app, IHostEnvironment env, IHangfireBackJob hangfire, LuceneIndexerOptions luceneIndexerOptions)
-		{
-			var are = new AutoResetEvent(false);
-			Task.Run(() =>
-			{
-				Console.WriteLine("正在导入自定义词库...");
-				double time = HiPerfTimer.Execute(() =>
-				{
-					var db = app.ApplicationServices.GetRequiredService<DataContext>();
-					var set = db.Post.Select(p => $"{p.Title},{p.Label},{p.Keyword}").AsParallel().SelectMany(s => Regex.Split(s, @"\p{P}(?<!\.|#)|\p{Z}|\p{S}")).Where(s => s.Length > 1).ToHashSet();
-					var lines = File.ReadAllLines(Path.Combine(env.ContentRootPath, "App_Data", "CustomKeywords.txt")).Union(set);
-					KeywordsManager.AddWords(lines);
-					KeywordsManager.AddSynonyms(File.ReadAllLines(Path.Combine(env.ContentRootPath, "App_Data", "CustomSynonym.txt")).Where(s => s.Contains(" ")).Select(s =>
-					{
-						var arr = Regex.Split(s, "\\s");
-						return (arr[0], arr[1]);
-					}));
-				});
-				Console.WriteLine($"导入自定义词库完成,耗时{time}s");
-				Windows.ClearMemorySilent();
-				are.Set();
-			});
-
-			string lucenePath = Path.Combine(env.ContentRootPath, luceneIndexerOptions.Path);
-			if (!Directory.Exists(lucenePath) || Directory.GetFiles(lucenePath).Length < 1)
-			{
-				are.WaitOne();
-				Console.WriteLine("索引库不存在,开始自动创建Lucene索引库...");
-				hangfire.CreateLuceneIndex();
-				Console.WriteLine("索引库创建完成!");
-			}
-		}
-
-		public static void SetupHangfire(this IApplicationBuilder app)
-		{
-			app.UseHangfireDashboard("/taskcenter", new DashboardOptions()
-			{
-				Authorization = new[]
-				{
-					new MyRestrictiveAuthorizationFilter()
-				}
-			}); //配置hangfire
-			HangfireJobInit.Start(); //初始化定时任务
-		}
-
-		public static void SetupHttpsRedirection(this IApplicationBuilder app, IConfiguration config)
-		{
-			if (bool.Parse(config["Https:Enabled"]))
-			{
-				app.UseHttpsRedirection();
-			}
-
-			var options = new RewriteOptions().Add(c =>
-			{
-				if (c.HttpContext.Request.Path.Equals("/tag") && c.HttpContext.Request.Query.ContainsKey("tag"))
-				{
-					c.Result = RuleResult.EndResponse;
-					c.HttpContext.Response.Redirect("/tag/" + HttpUtility.UrlEncode(c.HttpContext.Request.Query["tag"]), true);
-				}
-
-				if ((c.HttpContext.Request.Path.Equals("/search") || c.HttpContext.Request.Path.Equals("/s")) && c.HttpContext.Request.Query.ContainsKey("wd"))
-				{
-					c.Result = RuleResult.EndResponse;
-					c.HttpContext.Response.Redirect("/search/" + HttpUtility.UrlEncode(c.HttpContext.Request.Query["wd"]).Replace("+", "%20"), true);
-				}
-			}).AddRewrite(@"\w+/_blazor(.*)", "_blazor$1", false);
-			switch (config["UseRewriter"])
-			{
-				case "NonWww":
-					options.AddRedirectToNonWww(301); // URL重写
-					break;
-
-				case "WWW":
-					options.AddRedirectToWww(301); // URL重写
-					break;
-			}
-
-			app.UseRewriter(options);
-		}
-
-		public static void SetupMiniProfile(this IServiceCollection services)
-		{
-			services.AddMiniProfiler(options =>
-			{
-				options.RouteBasePath = "/profiler";
-				options.EnableServerTimingHeader = true;
-				options.ResultsAuthorize = req => req.HttpContext.Session.Get<UserInfoDto>(SessionKey.UserInfo)?.IsAdmin == true;
-				options.ResultsListAuthorize = options.ResultsAuthorize;
-				options.IgnoredPaths.AddRange("/Assets/", "/Content/", "/fonts/", "/images/", "/ng-views/", "/Scripts/", "/static/", "/template/", "/cloud10.png", "/favicon.ico", "/_blazor");
-				options.PopupRenderPosition = RenderPosition.BottomLeft;
-				options.PopupShowTimeWithChildren = true;
-				options.PopupShowTrivial = true;
-			}).AddEntityFramework();
-		}
-
-		public static void ConfigureOptions(this IServiceCollection services)
-		{
-			services.Configure<CookiePolicyOptions>(options =>
-			{
-				options.MinimumSameSitePolicy = SameSiteMode.Lax;
-			}); //配置Cookie策略
-			services.Configure<FormOptions>(options =>
-			{
-				options.MultipartBodyLengthLimit = 104857600; // 100MB
-			}); //配置请求长度
-			services.Configure<ForwardedHeadersOptions>(options => // X-Forwarded-For
-			{
-				options.ForwardLimit = null;
-				options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
-				options.ForwardedForHeaderName = AppConfig.TrueClientIPHeader;
-				options.KnownNetworks.Clear();
-				options.KnownProxies.Clear();
-			});
-			services.Configure<StaticFileOptions>(options =>
-			{
-				options.OnPrepareResponse = context =>
-				{
-					context.Context.Response.Headers[HeaderNames.CacheControl] = "public,no-cache";
-					context.Context.Response.Headers[HeaderNames.Expires] = DateTime.Now.AddDays(7).ToString("R");
-				};
-				options.ContentTypeProvider = new FileExtensionContentTypeProvider(MimeMapper.MimeTypes);
-				options.HttpsCompression = HttpsCompressionMode.Compress;
-			}); // 配置静态资源文件类型和缓存
-		}
-
-		public static IServiceCollection SetupHttpClients(this IServiceCollection services, IConfiguration config)
-		{
-			services.AddHttpClient("").AddTransientHttpErrorPolicy(builder => builder.Or<TaskCanceledException>().Or<OperationCanceledException>().Or<TimeoutException>().OrResult(res => !res.IsSuccessStatusCode).RetryAsync(5)).ConfigurePrimaryHttpMessageHandler(() =>
-			{
-				var handler = new HttpClientHandler
-				{
-					AutomaticDecompression = DecompressionMethods.All,
-					ClientCertificateOptions = ClientCertificateOption.Manual,
-					ServerCertificateCustomValidationCallback = (_, _, _, _) => true
-				};
-				if (bool.TryParse(config["HttpClientProxy:Enabled"], out var b) && b)
-				{
-					handler.Proxy = new WebProxy(config["HttpClientProxy:Uri"], true); // 使用自定义代理
-				}
-				else
-				{
-					handler.Proxy = WebRequest.GetSystemWebProxy(); // 使用系统代理
-				}
-
-				return handler;
-			}); //注入HttpClient
-			services.AddHttpClient<ImagebedClient>().AddTransientHttpErrorPolicy(builder => builder.Or<TaskCanceledException>().Or<OperationCanceledException>().Or<TimeoutException>().OrResult(res => !res.IsSuccessStatusCode).RetryAsync(3)); //注入HttpClient
-			return services;
-		}
-
-		public static IServiceCollection SetupImageSharp(this IServiceCollection services)
-		{
-			services.AddImageSharp(options =>
-			{
-				options.MemoryStreamManager = new RecyclableMemoryStreamManager();
-				options.BrowserMaxAge = TimeSpan.FromDays(7);
-				options.CacheMaxAge = TimeSpan.FromDays(365);
-				options.Configuration = SixLabors.ImageSharp.Configuration.Default;
-			}).SetRequestParser<QueryCollectionRequestParser>().Configure<PhysicalFileSystemCacheOptions>(options =>
-			{
-				options.CacheRootPath = null;
-				options.CacheFolder = "static/image_cache";
-			}).SetCache<PhysicalFileSystemCache>().SetCacheKey<UriRelativeLowerInvariantCacheKey>().SetCacheHash<SHA256CacheHash>().Configure<PhysicalFileSystemProviderOptions>(options =>
-			{
-				options.ProviderRootPath = null;
-			}).AddProvider<PhysicalFileSystemProvider>().AddProcessor<ResizeWebProcessor>().AddProcessor<FormatWebProcessor>().AddProcessor<BackgroundColorWebProcessor>().AddProcessor<QualityWebProcessor>().AddProcessor<AutoOrientWebProcessor>();
-			return services;
-		}
-
-	}
-
-	/// <summary>
-	/// hangfire授权拦截器
-	/// </summary>
-	public class MyRestrictiveAuthorizationFilter : IDashboardAuthorizationFilter
-	{
-		/// <summary>
-		/// 授权校验
-		/// </summary>
-		/// <param name="context"></param>
-		/// <returns></returns>
-		public bool Authorize(DashboardContext context)
-		{
+    public static class PrepareStartup
+    {
+        /// <summary>
+        /// 初始化系统设置参数
+        /// </summary>
+        /// <param name="app"></param>
+        internal static void InitSettings(this IApplicationBuilder app)
+        {
+            var dic = app.ApplicationServices.GetRequiredService<DataContext>().SystemSetting.ToDictionary(s => s.Name, s => s.Value);
+            CommonHelper.SystemSettings.AddOrUpdate(dic);
+        }
+
+        internal static void UseLuceneSearch(this IApplicationBuilder app, IHostEnvironment env, IHangfireBackJob hangfire, LuceneIndexerOptions luceneIndexerOptions)
+        {
+            var are = new AutoResetEvent(false);
+            Task.Run(() =>
+            {
+                Console.WriteLine("正在导入自定义词库...");
+                double time = HiPerfTimer.Execute(() =>
+                {
+                    var db = app.ApplicationServices.GetRequiredService<DataContext>();
+                    var set = db.Post.Select(p => $"{p.Title},{p.Label},{p.Keyword}").AsParallel().SelectMany(s => Regex.Split(s, @"\p{P}(?<!\.|#)|\p{Z}|\p{S}")).Where(s => s.Length > 1).ToHashSet();
+                    var lines = File.ReadAllLines(Path.Combine(env.ContentRootPath, "App_Data", "CustomKeywords.txt")).Union(set);
+                    KeywordsManager.AddWords(lines);
+                    KeywordsManager.AddSynonyms(File.ReadAllLines(Path.Combine(env.ContentRootPath, "App_Data", "CustomSynonym.txt")).Where(s => s.Contains(" ")).Select(s =>
+                    {
+                        var arr = Regex.Split(s, "\\s");
+                        return (arr[0], arr[1]);
+                    }));
+                });
+                Console.WriteLine($"导入自定义词库完成,耗时{time}s");
+                Windows.ClearMemorySilent();
+                are.Set();
+            });
+
+            string lucenePath = Path.Combine(env.ContentRootPath, luceneIndexerOptions.Path);
+            if (!Directory.Exists(lucenePath) || Directory.GetFiles(lucenePath).Length < 1)
+            {
+                are.WaitOne();
+                Console.WriteLine("索引库不存在,开始自动创建Lucene索引库...");
+                hangfire.CreateLuceneIndex();
+                Console.WriteLine("索引库创建完成!");
+            }
+        }
+
+        public static void SetupHangfire(this IApplicationBuilder app)
+        {
+            app.UseHangfireDashboard("/taskcenter", new DashboardOptions()
+            {
+                Authorization = new[]
+                {
+                    new MyRestrictiveAuthorizationFilter()
+                }
+            }); //配置hangfire
+            HangfireJobInit.Start(); //初始化定时任务
+        }
+
+        public static void SetupHttpsRedirection(this IApplicationBuilder app, IConfiguration config)
+        {
+            if (bool.Parse(config["Https:Enabled"]))
+            {
+                app.UseHttpsRedirection();
+            }
+
+            var options = new RewriteOptions().Add(c =>
+            {
+                if (c.HttpContext.Request.Path.Equals("/tag") && c.HttpContext.Request.Query.ContainsKey("tag"))
+                {
+                    c.Result = RuleResult.EndResponse;
+                    c.HttpContext.Response.Redirect("/tag/" + HttpUtility.UrlEncode(c.HttpContext.Request.Query["tag"]), true);
+                }
+
+                if ((c.HttpContext.Request.Path.Equals("/search") || c.HttpContext.Request.Path.Equals("/s")) && c.HttpContext.Request.Query.ContainsKey("wd"))
+                {
+                    c.Result = RuleResult.EndResponse;
+                    c.HttpContext.Response.Redirect("/search/" + HttpUtility.UrlEncode(c.HttpContext.Request.Query["wd"]).Replace("+", "%20"), true);
+                }
+            }).AddRewrite(@"\w+/_blazor(.*)", "_blazor$1", false);
+            switch (config["UseRewriter"])
+            {
+                case "NonWww":
+                    options.AddRedirectToNonWww(301); // URL重写
+                    break;
+
+                case "WWW":
+                    options.AddRedirectToWww(301); // URL重写
+                    break;
+            }
+
+            app.UseRewriter(options);
+        }
+
+        public static void SetupMiniProfile(this IServiceCollection services)
+        {
+            services.AddMiniProfiler(options =>
+            {
+                options.RouteBasePath = "/profiler";
+                options.EnableServerTimingHeader = true;
+                options.ResultsAuthorize = req => req.HttpContext.Session.Get<UserInfoDto>(SessionKey.UserInfo)?.IsAdmin == true;
+                options.ResultsListAuthorize = options.ResultsAuthorize;
+                options.IgnoredPaths.AddRange("/Assets/", "/Content/", "/fonts/", "/images/", "/ng-views/", "/Scripts/", "/static/", "/template/", "/cloud10.png", "/favicon.ico", "/_blazor");
+                options.PopupRenderPosition = RenderPosition.BottomLeft;
+                options.PopupShowTimeWithChildren = true;
+                options.PopupShowTrivial = true;
+            }).AddEntityFramework();
+        }
+
+        public static void ConfigureOptions(this IServiceCollection services)
+        {
+            services.Configure<CookiePolicyOptions>(options =>
+            {
+                options.MinimumSameSitePolicy = SameSiteMode.Lax;
+            }); //配置Cookie策略
+            services.Configure<FormOptions>(options =>
+            {
+                options.MultipartBodyLengthLimit = 104857600; // 100MB
+            }); //配置请求长度
+            services.Configure<ForwardedHeadersOptions>(options => // X-Forwarded-For
+            {
+                options.ForwardLimit = null;
+                options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
+                options.ForwardedForHeaderName = AppConfig.TrueClientIPHeader;
+                options.KnownNetworks.Clear();
+                options.KnownProxies.Clear();
+            });
+            services.Configure<StaticFileOptions>(options =>
+            {
+                options.OnPrepareResponse = context =>
+                {
+                    context.Context.Response.Headers[HeaderNames.CacheControl] = "public,no-cache";
+                    context.Context.Response.Headers[HeaderNames.Expires] = DateTime.Now.AddDays(7).ToString("R");
+                };
+                options.ContentTypeProvider = new FileExtensionContentTypeProvider(MimeMapper.MimeTypes);
+                options.HttpsCompression = HttpsCompressionMode.Compress;
+            }); // 配置静态资源文件类型和缓存
+        }
+
+        public static IServiceCollection SetupHttpClients(this IServiceCollection services, IConfiguration config)
+        {
+            services.AddHttpClient("").AddTransientHttpErrorPolicy(builder => builder.Or<TaskCanceledException>().Or<OperationCanceledException>().Or<TimeoutException>().OrResult(res => !res.IsSuccessStatusCode).RetryAsync(5)).ConfigurePrimaryHttpMessageHandler(() =>
+            {
+                var handler = new HttpClientHandler
+                {
+                    AutomaticDecompression = DecompressionMethods.All,
+                    ClientCertificateOptions = ClientCertificateOption.Manual,
+                    ServerCertificateCustomValidationCallback = (_, _, _, _) => true
+                };
+                if (bool.TryParse(config["HttpClientProxy:Enabled"], out var b) && b)
+                {
+                    handler.Proxy = new WebProxy(config["HttpClientProxy:Uri"], true); // 使用自定义代理
+                }
+                else
+                {
+                    handler.Proxy = WebRequest.GetSystemWebProxy(); // 使用系统代理
+                }
+
+                return handler;
+            }); //注入HttpClient
+            services.AddHttpClient<ImagebedClient>().AddTransientHttpErrorPolicy(builder => builder.Or<TaskCanceledException>().Or<OperationCanceledException>().Or<TimeoutException>().OrResult(res => !res.IsSuccessStatusCode).RetryAsync(3)); //注入HttpClient
+            return services;
+        }
+
+        public static IServiceCollection SetupImageSharp(this IServiceCollection services)
+        {
+            services.AddImageSharp(options =>
+            {
+                options.MemoryStreamManager = new RecyclableMemoryStreamManager();
+                options.BrowserMaxAge = TimeSpan.FromDays(7);
+                options.CacheMaxAge = TimeSpan.FromDays(365);
+                options.Configuration = SixLabors.ImageSharp.Configuration.Default;
+            }).SetRequestParser<QueryCollectionRequestParser>().Configure<PhysicalFileSystemCacheOptions>(options =>
+            {
+                options.CacheRootPath = null;
+                options.CacheFolder = "static/image_cache";
+            }).SetCache<PhysicalFileSystemCache>().SetCacheKey<UriRelativeLowerInvariantCacheKey>().SetCacheHash<SHA256CacheHash>().Configure<PhysicalFileSystemProviderOptions>(options =>
+            {
+                options.ProviderRootPath = null;
+            }).AddProvider<PhysicalFileSystemProvider>().AddProcessor<ResizeWebProcessor>().AddProcessor<FormatWebProcessor>().AddProcessor<BackgroundColorWebProcessor>().AddProcessor<QualityWebProcessor>().AddProcessor<AutoOrientWebProcessor>();
+            return services;
+        }
+    }
+
+    /// <summary>
+    /// hangfire授权拦截器
+    /// </summary>
+    public class MyRestrictiveAuthorizationFilter : IDashboardAuthorizationFilter
+    {
+        /// <summary>
+        /// 授权校验
+        /// </summary>
+        /// <param name="context"></param>
+        /// <returns></returns>
+        public bool Authorize(DashboardContext context)
+        {
 #if DEBUG
-			return true;
+            return true;
 #endif
-			var user = context.GetHttpContext().Session.Get<UserInfoDto>(SessionKey.UserInfo) ?? new UserInfoDto();
-			return user.IsAdmin;
-		}
-	}
+            var user = context.GetHttpContext().Session.Get<UserInfoDto>(SessionKey.UserInfo) ?? new UserInfoDto();
+            return user.IsAdmin;
+        }
+    }
 }

+ 1 - 1
src/Masuit.MyBlogs.Core/Startup.cs

@@ -13,7 +13,7 @@ using Masuit.MyBlogs.Core.Extensions;
 using Masuit.MyBlogs.Core.Extensions.DriveHelpers;
 using Masuit.MyBlogs.Core.Extensions.Firewall;
 using Masuit.MyBlogs.Core.Extensions.Hangfire;
-using Masuit.Tools.AspNetCore.Mime;
+using Masuit.Tools.Mime;
 using Masuit.Tools.Config;
 using Masuit.Tools.Core.AspNetCore;
 using Microsoft.EntityFrameworkCore;