Browse Source

1. 防火墙优化;
2. 黑科技页改进

懒得勤快 4 years ago
parent
commit
31ca79880e

+ 7 - 1
src/Masuit.MyBlogs.Core/Controllers/LinksController.cs

@@ -45,7 +45,7 @@ namespace Masuit.MyBlogs.Core.Controllers
         /// <returns></returns>
         public async Task<ActionResult> Apply(Links links, CancellationToken cancellationToken)
         {
-            if (!links.Url.MatchUrl()||links.Url.Contains(Request.Host.Host))
+            if (!links.Url.MatchUrl() || links.Url.Contains(Request.Host.Host))
             {
                 return ResultData(null, false, "添加失败!链接非法!");
             }
@@ -58,6 +58,9 @@ namespace Masuit.MyBlogs.Core.Controllers
 
             HttpClient.DefaultRequestHeaders.UserAgent.Add(ProductInfoHeaderValue.Parse("Mozilla/5.0"));
             HttpClient.DefaultRequestHeaders.Referrer = new Uri(Request.Scheme + "://" + Request.Host);
+            HttpClient.DefaultRequestHeaders.Add("X-Forwarded-For", "1.1.1.1");
+            HttpClient.DefaultRequestHeaders.Add("X-Forwarded-Host", "1.1.1.1");
+            HttpClient.DefaultRequestHeaders.Add("X-Real-IP", "1.1.1.1");
             return await await HttpClient.GetAsync(links.Url, cancellationToken).ContinueWith(async t =>
             {
                 if (t.IsFaulted || t.IsCanceled)
@@ -131,6 +134,9 @@ namespace Masuit.MyBlogs.Core.Controllers
         public async Task<ActionResult> Check(string link)
         {
             HttpClient.DefaultRequestHeaders.UserAgent.Add(ProductInfoHeaderValue.Parse("Mozilla/5.0"));
+            HttpClient.DefaultRequestHeaders.Add("X-Forwarded-For", "1.1.1.1");
+            HttpClient.DefaultRequestHeaders.Add("X-Forwarded-Host", "1.1.1.1");
+            HttpClient.DefaultRequestHeaders.Add("X-Real-IP", "1.1.1.1");
             using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
             return await HttpClient.GetAsync(link, cts.Token).ContinueWith(t =>
             {

+ 15 - 15
src/Masuit.MyBlogs.Core/Controllers/MsgController.cs

@@ -305,6 +305,21 @@ namespace Masuit.MyBlogs.Core.Controllers
             return Content("ok");
         }
 
+        /// <summary>
+        /// 标记为已读
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        [MyAuthorize]
+        public async Task<ActionResult> MarkRead(int id)
+        {
+            await MessageService.GetQuery(m => m.Id <= id).UpdateFromQueryAsync(m => new InternalMessage()
+            {
+                Read = true
+            });
+            return ResultData(null);
+        }
+
         /// <summary>
         /// 删除站内信
         /// </summary>
@@ -352,21 +367,6 @@ namespace Masuit.MyBlogs.Core.Controllers
             return ResultData(null, true, "站内消息清除成功!");
         }
 
-        /// <summary>
-        /// 标记为已读
-        /// </summary>
-        /// <param name="id"></param>
-        /// <returns></returns>
-        [MyAuthorize]
-        public async Task<ActionResult> MarkRead(int id)
-        {
-            await MessageService.GetQuery(m => m.Id <= id).UpdateFromQueryAsync(m => new InternalMessage()
-            {
-                Read = true
-            });
-            return ResultData(null);
-        }
-
         #endregion
     }
 }

+ 5 - 4
src/Masuit.MyBlogs.Core/Controllers/PostController.cs

@@ -40,7 +40,6 @@ using System.Linq.Expressions;
 using System.Text.RegularExpressions;
 using System.Threading;
 using System.Threading.Tasks;
-using Z.EntityFramework.Plus;
 using SameSiteMode = Microsoft.AspNetCore.Http.SameSiteMode;
 
 namespace Masuit.MyBlogs.Core.Controllers
@@ -144,14 +143,16 @@ namespace Masuit.MyBlogs.Core.Controllers
 
         private void Disallow(Post post)
         {
-            BackgroundJob.Enqueue(() => HangfireBackJob.InterceptLog(new IpIntercepter()
+            RedisHelper.IncrBy("interceptCount");
+            RedisHelper.LPush("intercept", new IpIntercepter()
             {
                 IP = ClientIP,
                 RequestUrl = $"//{Request.Host}/{post.Id}",
                 Time = DateTime.Now,
                 UserAgent = Request.Headers[HeaderNames.UserAgent],
-                Remark = "无权限查看该文章"
-            }));
+                Remark = "无权限查看该文章",
+                Address = Request.Location()
+            });
             throw new NotFoundException("文章未找到");
         }
 

+ 11 - 26
src/Masuit.MyBlogs.Core/Controllers/ToolsController.cs

@@ -1,7 +1,7 @@
 using Masuit.MyBlogs.Core.Common;
 using Masuit.MyBlogs.Core.Configs;
+using Masuit.MyBlogs.Core.Models.ViewModel;
 using Masuit.Tools;
-using Masuit.Tools.Core.Net;
 using Masuit.Tools.Core.Validator;
 using Masuit.Tools.Models;
 using MaxMind.GeoIP2.Exceptions;
@@ -40,7 +40,7 @@ namespace Masuit.MyBlogs.Core.Controllers
         /// <param name="ip"></param>
         /// <returns></returns>
         [Route("ip"), Route("ip/{ip?}", Order = 1), ResponseCache(Duration = 600, VaryByQueryKeys = new[] { "ip" }, VaryByHeader = "Cookie")]
-        public async Task<ActionResult> GetIpInfo([IsIPAddress] string ip)
+        public ActionResult GetIpInfo([IsIPAddress] string ip)
         {
             if (string.IsNullOrEmpty(ip))
             {
@@ -53,32 +53,19 @@ namespace Masuit.MyBlogs.Core.Controllers
             }
 
             ViewBag.IP = ip;
-            var location = Policy<CityResponse>.Handle<AddressNotFoundException>().Fallback(() => new CityResponse()).Execute(() => CommonHelper.MaxmindReader.City(ip));
-            var asn = ip.GetIPAsn();
-            var address = await ip.GetPhysicsAddressInfo() ?? new PhysicsAddress()
+            var cityInfo = Policy<CityResponse>.Handle<AddressNotFoundException>().Fallback(() => new CityResponse()).Execute(() => CommonHelper.MaxmindReader.City(ip));
+            var address = new IpInfo()
             {
-                Status = 0,
-                AddressResult = new AddressResult()
-                {
-                    AddressComponent = new AddressComponent(),
-                    FormattedAddress = ip.GetIPLocation(),
-                    Location = new Location()
-                    {
-                        Lng = location.Location.Longitude ?? 0,
-                        Lat = location.Location.Latitude ?? 0
-                    }
-                }
+                CityInfo = cityInfo,
+                Address = $"{ip.GetIPLocation()}(UTC{TZConvert.GetTimeZoneInfo(cityInfo.Location.TimeZone ?? "Asia/Shanghai").BaseUtcOffset.Hours:+#;-#;0})",
+                Asn = ip.GetIPAsn()
             };
-            address.AddressResult.Pois.Add(new Pois
-            {
-                AddressDetail = $"{ip.GetIPLocation()}(UTC{TZConvert.GetTimeZoneInfo(location.Location.TimeZone ?? "Asia/Shanghai").BaseUtcOffset.Hours:+#;-#;0},本地数据库)"
-            });
             if (Request.Method.Equals(HttpMethods.Get))
             {
-                return View((address, asn));
+                return View(address);
             }
 
-            return Json(new { address, asn });
+            return Json(address);
         }
 
         /// <summary>
@@ -98,12 +85,11 @@ namespace Masuit.MyBlogs.Core.Controllers
                 ip = $"{r.Next(210)}.{r.Next(255)}.{r.Next(255)}.{r.Next(255)}";
 #endif
                 var location = Policy<CityResponse>.Handle<AddressNotFoundException>().Fallback(() => new CityResponse()).Execute(() => CommonHelper.MaxmindReader.City(ip));
-                var address = await ip.GetPhysicsAddressInfo() ?? new PhysicsAddress()
+                var address = new PhysicsAddress()
                 {
                     Status = 0,
                     AddressResult = new AddressResult()
                     {
-                        AddressComponent = new AddressComponent(),
                         FormattedAddress = ip.GetIPLocation(),
                         Location = new Location()
                         {
@@ -144,12 +130,11 @@ namespace Masuit.MyBlogs.Core.Controllers
                 ip = $"{r.Next(210)}.{r.Next(255)}.{r.Next(255)}.{r.Next(255)}";
 #endif
                 var location = Policy<CityResponse>.Handle<AddressNotFoundException>().Fallback(() => new CityResponse()).Execute(() => CommonHelper.MaxmindReader.City(ip));
-                var address = await ip.GetPhysicsAddressInfo() ?? new PhysicsAddress()
+                var address = new PhysicsAddress()
                 {
                     Status = 0,
                     AddressResult = new AddressResult()
                     {
-                        AddressComponent = new AddressComponent(),
                         FormattedAddress = ip.GetIPLocation(),
                         Location = new Location()
                         {

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

@@ -1,8 +1,6 @@
 using CacheManager.Core;
-using Hangfire;
 using Masuit.MyBlogs.Core.Common;
 using Masuit.MyBlogs.Core.Configs;
-using Masuit.MyBlogs.Core.Extensions.Hangfire;
 using Masuit.Tools;
 using Masuit.Tools.AspNetCore.Mime;
 using Masuit.Tools.Logging;
@@ -90,14 +88,16 @@ namespace Masuit.MyBlogs.Core.Extensions.Firewall
         private async void AccessDeny(string ip, HttpRequest request, string remark)
         {
             var path = HttpUtility.UrlDecode(request.Path + request.QueryString, Encoding.UTF8);
-            BackgroundJob.Enqueue(() => HangfireBackJob.InterceptLog(new IpIntercepter()
+            await RedisHelper.IncrByAsync("interceptCount");
+            await RedisHelper.LPushAsync("intercept", new IpIntercepter()
             {
                 IP = ip,
                 RequestUrl = HttpUtility.UrlDecode(request.Scheme + "://" + request.Host + path),
                 Time = DateTime.Now,
                 UserAgent = request.Headers[HeaderNames.UserAgent],
-                Remark = remark
-            }));
+                Remark = "无权限查看该文章",
+                Address = request.Location()
+            });
             var limit = CommonHelper.SystemSettings.GetOrAdd("LimitIPInterceptTimes", "30").ToInt32();
             await RedisHelper.LRangeAsync<IpIntercepter>("intercept", 0, -1).ContinueWith(async t =>
             {

+ 7 - 6
src/Masuit.MyBlogs.Core/Extensions/Firewall/RequestInterceptMiddleware.cs

@@ -1,18 +1,17 @@
-using Hangfire;
-using Masuit.MyBlogs.Core.Common;
+using Masuit.MyBlogs.Core.Common;
 using Masuit.MyBlogs.Core.Configs;
 using Masuit.MyBlogs.Core.Extensions.Hangfire;
 using Masuit.MyBlogs.Core.Models.ViewModel;
 using Masuit.Tools;
 using Masuit.Tools.Core.Net;
 using Microsoft.AspNetCore.Http;
-using Microsoft.Net.Http.Headers;
 using System;
 using System.Linq;
 using System.Text;
 using System.Text.RegularExpressions;
 using System.Threading.Tasks;
 using System.Web;
+using HeaderNames = Microsoft.Net.Http.Headers.HeaderNames;
 
 namespace Masuit.MyBlogs.Core.Extensions.Firewall
 {
@@ -50,14 +49,16 @@ namespace Masuit.MyBlogs.Core.Extensions.Firewall
             var match = Regex.Match(path ?? "", CommonHelper.BanRegex);
             if (match.Length > 0)
             {
-                BackgroundJob.Enqueue(() => HangfireBackJob.InterceptLog(new IpIntercepter()
+                RedisHelper.IncrBy("interceptCount");
+                RedisHelper.LPush("intercept", new IpIntercepter()
                 {
                     IP = ip,
                     RequestUrl = requestUrl,
                     Time = DateTime.Now,
                     UserAgent = request.Headers[HeaderNames.UserAgent],
-                    Remark = $"检测到敏感词拦截:{match.Value}"
-                }));
+                    Remark = "无权限查看该文章",
+                    Address = request.Location()
+                });
                 context.Response.StatusCode = 400;
                 context.Response.ContentType = "text/html; charset=utf-8";
                 return context.Response.WriteAsync("参数不合法!", Encoding.UTF8);

+ 4 - 24
src/Masuit.MyBlogs.Core/Extensions/Hangfire/HangfireBackJob.cs

@@ -1,13 +1,11 @@
 using Masuit.LuceneEFCore.SearchEngine.Interfaces;
 using Masuit.MyBlogs.Core.Common;
-using Masuit.MyBlogs.Core.Extensions.Firewall;
 using Masuit.MyBlogs.Core.Infrastructure;
 using Masuit.MyBlogs.Core.Infrastructure.Services.Interface;
 using Masuit.MyBlogs.Core.Models.DTO;
 using Masuit.MyBlogs.Core.Models.Entity;
 using Masuit.MyBlogs.Core.Models.Enum;
 using Masuit.Tools;
-using Masuit.Tools.Core.Net;
 using Masuit.Tools.Strings;
 using Microsoft.AspNetCore.Hosting;
 using System;
@@ -69,21 +67,12 @@ namespace Masuit.MyBlogs.Core.Extensions.Hangfire
         /// <param name="type"></param>
         public void LoginRecord(UserInfoDto userInfo, string ip, LoginType type)
         {
-            var result = ip.GetPhysicsAddressInfo().Result;
-            if (result?.Status != 0)
-            {
-                return;
-            }
-
-            string addr = result.AddressResult.FormattedAddress;
-            string prov = result.AddressResult.AddressComponent.Province;
             var record = new LoginRecord()
             {
                 IP = ip,
                 LoginTime = DateTime.Now,
                 LoginType = type,
-                PhysicAddress = addr,
-                Province = prov
+                PhysicAddress = ip.GetIPLocation()
             };
             var u = _userInfoService.GetByUsername(userInfo.Username);
             u.LoginRecord.Add(record);
@@ -136,18 +125,6 @@ namespace Masuit.MyBlogs.Core.Extensions.Hangfire
             _postService.SaveChanges();
         }
 
-        /// <summary>
-        /// 防火墙拦截日志
-        /// </summary>
-        /// <param name="s"></param>
-        public static void InterceptLog(IpIntercepter s)
-        {
-            RedisHelper.IncrBy("interceptCount");
-            var result = s.IP.GetPhysicsAddressInfo().Result;
-            s.Address = result?.Status == 0 ? result.AddressResult.FormattedAddress : s.IP.GetIPLocation();
-            RedisHelper.LPush("intercept", s);
-        }
-
         /// <summary>
         /// 每天的任务
         /// </summary>
@@ -193,6 +170,9 @@ namespace Masuit.MyBlogs.Core.Extensions.Hangfire
         {
             var client = _httpClientFactory.CreateClient();
             client.DefaultRequestHeaders.UserAgent.Add(ProductInfoHeaderValue.Parse("Mozilla/5.0"));
+            client.DefaultRequestHeaders.Add("X-Forwarded-For", "1.1.1.1");
+            client.DefaultRequestHeaders.Add("X-Forwarded-Host", "1.1.1.1");
+            client.DefaultRequestHeaders.Add("X-Real-IP", "1.1.1.1");
             client.DefaultRequestHeaders.Referrer = new Uri("https://google.com");
             client.Timeout = TimeSpan.FromSeconds(10);
             _linksService.GetQuery(l => !l.Except).AsParallel().ForAll(link =>

+ 5 - 5
src/Masuit.MyBlogs.Core/Infrastructure/Repository/BaseRepository.cs

@@ -599,7 +599,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
         /// <returns>还未执行的SQL语句</returns>
         public virtual PagedList<T> GetPages<TS>(int pageIndex, int pageSize, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc)
         {
-            return isAsc ? DataContext.Set<T>().Where(where).OrderBy(orderby).ToPagedList(pageIndex, pageSize) : DataContext.Set<T>().Where(where).OrderByDescending(orderby).ToPagedList(pageIndex, pageSize);
+            return isAsc ? DataContext.Set<T>().Where(where).NotCacheable().OrderBy(orderby).ToPagedList(pageIndex, pageSize) : DataContext.Set<T>().Where(where).NotCacheable().OrderByDescending(orderby).ToPagedList(pageIndex, pageSize);
         }
 
         /// <summary>
@@ -614,7 +614,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
         /// <returns>还未执行的SQL语句</returns>
         public virtual Task<PagedList<T>> GetPagesAsync<TS>(int pageIndex, int pageSize, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> orderby, bool isAsc)
         {
-            return isAsc ? DataContext.Set<T>().Where(where).OrderBy(orderby).ToPagedListAsync(pageIndex, pageSize) : DataContext.Set<T>().Where(where).OrderByDescending(orderby).ToPagedListAsync(pageIndex, pageSize);
+            return isAsc ? DataContext.Set<T>().Where(where).NotCacheable().OrderBy(orderby).ToPagedListAsync(pageIndex, pageSize) : DataContext.Set<T>().Where(where).NotCacheable().OrderByDescending(orderby).ToPagedListAsync(pageIndex, pageSize);
         }
 
         /// <summary>
@@ -678,7 +678,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
         /// <returns>还未执行的SQL语句</returns>
         public virtual PagedList<T> GetPagesNoTracking<TS>(int pageIndex, int pageSize, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc = true)
         {
-            return isAsc ? DataContext.Set<T>().Where(where).AsNoTracking().OrderBy(orderby).ToPagedList(pageIndex, pageSize) : DataContext.Set<T>().Where(where).AsNoTracking().OrderByDescending(orderby).ToPagedList(pageIndex, pageSize);
+            return isAsc ? DataContext.Set<T>().Where(where).AsNoTracking().NotCacheable().OrderBy(orderby).ToPagedList(pageIndex, pageSize) : DataContext.Set<T>().Where(where).AsNoTracking().NotCacheable().OrderByDescending(orderby).ToPagedList(pageIndex, pageSize);
         }
 
         /// <summary>
@@ -968,7 +968,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
                 page = 1;
             }
 
-            var list = query.Skip(size * (page - 1)).Take(size).ProjectTo<TDto>(mapper).ToList();
+            var list = query.Skip(size * (page - 1)).Take(size).ProjectTo<TDto>(mapper).NotCacheable().ToList();
             return new PagedList<TDto>(list, page, size, totalCount);
         }
 
@@ -995,7 +995,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
                 page = 1;
             }
 
-            var list = await query.Skip(size * (page - 1)).Take(size).ProjectTo<TDto>(mapper).ToListAsync();
+            var list = await query.Skip(size * (page - 1)).Take(size).ProjectTo<TDto>(mapper).NotCacheable().ToListAsync();
             return new PagedList<TDto>(list, page, size, totalCount);
         }
 

+ 4 - 2
src/Masuit.MyBlogs.Core/Infrastructure/Services/AdvertisementService.cs

@@ -42,7 +42,8 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services
         {
             return CacheManager.GetOrAdd($"{type}:{count}-{cid}", _ =>
             {
-                Expression<Func<Advertisement, bool>> where = a => a.Types.Contains(type.ToString("D")) && a.Status == Status.Available;
+                var atype = type.ToString("D");
+                Expression<Func<Advertisement, bool>> where = a => a.Types.Contains(atype) && a.Status == Status.Available;
                 if (cid.HasValue)
                 {
                     var scid = cid.ToString();
@@ -51,7 +52,8 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services
                         @where = @where.And(a => a.CategoryIds.Contains(scid) || string.IsNullOrEmpty(a.CategoryIds));
                     }
                 }
-                var list = GetQuery(where).OrderBy(a => -Math.Log(DataContext.Random()) / (double)a.Price * (string.IsNullOrEmpty(a.CategoryIds) ? 2 : 1)).Take(count).ToList();
+
+                var list = GetQuery(where).OrderBy(a => -Math.Log(DataContext.Random()) / (double)a.Price * (string.IsNullOrEmpty(a.CategoryIds) ? 5 : 1)).Take(count).ToList();
                 var ids = list.Select(a => a.Id).ToArray();
                 GetQuery(a => ids.Contains(a.Id)).UpdateFromQuery(a => new Advertisement()
                 {

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

@@ -47,7 +47,7 @@
         <PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="5.0.7" />
         <PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="5.0.7" />
         <PackageReference Include="Microsoft.Extensions.Http.Polly" Version="5.0.1" />
-        <PackageReference Include="Microsoft.Graph" Version="3.33.0" />
+        <PackageReference Include="Microsoft.Graph" Version="3.35.0" />
         <PackageReference Include="Microsoft.Graph.Auth" Version="1.0.0-preview.6" />
         <PackageReference Include="MiniProfiler.AspNetCore.Mvc" Version="4.2.22" />
         <PackageReference Include="OpenXmlPowerTools-NetStandard" Version="4.4.21" />
@@ -59,7 +59,7 @@
         <PackageReference Include="TimeZoneConverter" Version="3.5.0" />
         <PackageReference Include="WilderMinds.RssSyndication" Version="1.7.0" />
         <PackageReference Include="WinInsider.System.Net.Http.Formatting" Version="1.0.14" />
-        <PackageReference Include="Z.EntityFramework.Plus.EFCore" Version="5.1.39" />
+        <PackageReference Include="Z.EntityFramework.Plus.EFCore" Version="5.1.41" />
     </ItemGroup>
     <ItemGroup>
         <Content Update="appsettings.json">

+ 0 - 5
src/Masuit.MyBlogs.Core/Models/Entity/LoginRecord.cs

@@ -20,11 +20,6 @@ namespace Masuit.MyBlogs.Core.Models.Entity
         /// </summary>
         public DateTime LoginTime { get; set; }
 
-        /// <summary>
-        /// 登录地所在省份
-        /// </summary>
-        public string Province { get; set; }
-
         /// <summary>
         /// 地理位置
         /// </summary>

+ 11 - 0
src/Masuit.MyBlogs.Core/Models/ViewModel/IpInfo.cs

@@ -0,0 +1,11 @@
+using MaxMind.GeoIP2.Responses;
+
+namespace Masuit.MyBlogs.Core.Models.ViewModel
+{
+    public class IpInfo
+    {
+        public string Address { get; set; }
+        public CityResponse CityInfo { get; set; }
+        public AsnResponse Asn { get; set; }
+    }
+}

+ 116 - 0
src/Masuit.MyBlogs.Core/Models/ViewModel/PhysicsAddress.cs

@@ -0,0 +1,116 @@
+using Newtonsoft.Json;
+using System.Collections.Generic;
+
+namespace Masuit.Tools.Models
+{
+    /// <summary>
+    /// 详细地理信息
+    /// </summary>
+    public class PhysicsAddress
+    {
+        /// <summary>
+        /// 返回状态,0正常,1出错
+        /// </summary>
+        [JsonProperty("status")]
+        public int Status { get; set; }
+
+        /// <summary>
+        /// 返回结果集
+        /// </summary>
+        [JsonProperty("result")]
+        public AddressResult AddressResult { get; set; } = new AddressResult();
+    }
+    /// <summary>
+    /// 返回结果集
+    /// </summary>
+    public class AddressResult
+    {
+        /// <summary>
+        /// 经纬度
+        /// </summary>
+        [JsonProperty("location")]
+        public Location Location { get; set; }
+
+        /// <summary>
+        /// 详细地址
+        /// </summary>
+        [JsonProperty("formatted_address")]
+        public string FormattedAddress { get; set; }
+
+        /// <summary>
+        /// 商业地址
+        /// </summary>
+        [JsonProperty("business")]
+        public string Business { get; set; }
+
+        /// <summary>
+        /// 参考地址
+        /// </summary>
+        [JsonProperty("pois")]
+        public List<Pois> Pois { get; set; } = new List<Pois>();
+
+        /// <summary>
+        /// 语义描述
+        /// </summary>
+        [JsonProperty("sematic_description")]
+        public string SematicDescription { get; set; }
+    }
+    /// <summary>
+    /// 参考位置
+    /// </summary>
+    public class Pois
+    {
+        /// <summary>
+        /// 地理位置详细
+        /// </summary>
+        [JsonProperty("addr")]
+        public string AddressDetail { get; set; }
+
+        /// <summary>
+        /// 方位
+        /// </summary>
+        [JsonProperty("direction")]
+        public string Direction { get; set; }
+
+        /// <summary>
+        /// 距离
+        /// </summary>
+        [JsonProperty("distance")]
+        public string Distance { get; set; } = "0";
+
+        /// <summary>
+        /// 建筑物名字
+        /// </summary>
+        [JsonProperty("name")]
+        public string Name { get; set; }
+
+        /// <summary>
+        /// 建筑物类型
+        /// </summary>
+        [JsonProperty("poiType")]
+        public string PoiType { get; set; }
+
+        /// <summary>
+        /// 标签
+        /// </summary>
+        [JsonProperty("tag")]
+        public string Tag { get; set; }
+    }
+    /// <summary>
+    /// 经纬度
+    /// </summary>
+    public class Location
+    {
+        /// <summary>
+        /// 经度
+        /// </summary>
+        [JsonProperty("lng")]
+        public double Lng { get; set; }
+
+        /// <summary>
+        /// 纬度
+        /// </summary>
+        [JsonProperty("lat")]
+        public double Lat { get; set; }
+    }
+}

+ 15 - 2
src/Masuit.MyBlogs.Core/Startup.cs

@@ -30,6 +30,8 @@ using Microsoft.Extensions.Hosting;
 using Microsoft.Extensions.Primitives;
 using Polly;
 using System;
+using System.Net;
+using System.Net.Http;
 using System.Threading.Tasks;
 
 namespace Masuit.MyBlogs.Core
@@ -107,8 +109,19 @@ namespace Masuit.MyBlogs.Core
                 Path = "lucene"
             }); // 配置7z和断点续传和Redis和Lucene搜索引擎
 
-            services.AddHttpClient("", c => c.Timeout = TimeSpan.FromSeconds(30)).AddTransientHttpErrorPolicy(builder => builder.Or<TaskCanceledException>().Or<OperationCanceledException>().Or<TimeoutException>().OrResult(res => !res.IsSuccessStatusCode).RetryAsync(5)); //注入HttpClient
-            services.AddHttpClient<ImagebedClient>().AddTransientHttpErrorPolicy(builder => builder.Or<TaskCanceledException>().Or<OperationCanceledException>().Or<TimeoutException>().OrResult(res => !res.IsSuccessStatusCode).RetryAsync(5));
+            services.AddHttpClient("", c => c.Timeout = TimeSpan.FromSeconds(30)).AddTransientHttpErrorPolicy(builder => builder.Or<TaskCanceledException>().Or<OperationCanceledException>().Or<TimeoutException>().OrResult(res => !res.IsSuccessStatusCode).RetryAsync(5)).ConfigurePrimaryHttpMessageHandler(() =>
+            {
+                if (bool.TryParse(Configuration["HttpClientProxy:Enabled"], out var b) && b)
+                {
+                    return new HttpClientHandler
+                    {
+                        Proxy = new WebProxy(Configuration["HttpClientProxy:Uri"], true)
+                    };
+                }
+
+                return new HttpClientHandler();
+            }); //注入HttpClient
+            services.AddHttpClient<ImagebedClient>().AddTransientHttpErrorPolicy(builder => builder.Or<TaskCanceledException>().Or<OperationCanceledException>().Or<TimeoutException>().OrResult(res => !res.IsSuccessStatusCode).RetryAsync(5)); //注入HttpClient
             services.AddMailSender(Configuration).AddFirewallReporter(Configuration);
             services.AddBundling().UseDefaults(_env).UseNUglify().EnableMinification().EnableChangeDetection().EnableCacheHeader(TimeSpan.FromHours(1));
             services.SetupMiniProfile();

+ 26 - 51
src/Masuit.MyBlogs.Core/Views/Tools/GetIPInfo.cshtml

@@ -1,5 +1,4 @@
-@using Masuit.Tools.Models
-@model (PhysicsAddress address, MaxMind.GeoIP2.Responses.AsnResponse asn)
+@model Masuit.MyBlogs.Core.Models.ViewModel.IpInfo
 @{
     ViewBag.Title = "获取IP地址详细地理位置信息";
     Layout = "~/Views/Shared/_Layout.cshtml";
@@ -32,65 +31,41 @@
             </span>
         </div>
     </form>
-    @if (Model.address != null && Model.address.Status == 0)
-    {
-        int count = 0;
-        <table class="table table-bordered table-condensed table-hover">
-            <tr>
-                <td>IP路由信息:</td>
-                <td>@Model.asn.Network</td>
-            </tr>
-            <tr>
-                <td>IP机房信息:</td>
-                <td>@Model.asn.AutonomousSystemOrganization</td>
-            </tr>
-            <tr>
-                <td>ASN:</td>
-                <td>@Model.asn.AutonomousSystemNumber</td>
-            </tr>
-            <tr>
-                <td>-</td>
-                <td>-</td>
-            </tr>
-            <tr>
-                <td>参考地理位置:</td>
-                <td>@Model.address.AddressResult.FormattedAddress</td>
-            </tr>
-            <tr>
-                <td>标志性商业街:</td>
-                <td>@Model.address.AddressResult.Business</td>
-            </tr>
-            <tr>
-                <td>经纬度:</td>
-                <td>(经度:@(Model.address.AddressResult.Location?.Lng),纬度:@(Model.address.AddressResult.Location?.Lat))</td>
-            </tr>
-            @foreach (Pois poi in Model.address.AddressResult.Pois)
-            {
-                <tr>
-                    <td>参考地理位置@(++count):</td>
-                    <td>@poi.AddressDetail</td>
-                </tr>
-            }
-        </table>
-
-    }
-    else
-    {
-        <span class="text-danger">@ViewBag.IP 未找到或者不是一个有效的IPv4外网地址</span>
-    }
+    <table class="table table-bordered table-condensed table-hover">
+        <tr>
+            <td>IP路由信息:</td>
+            <td>@Model.Asn.Network</td>
+        </tr>
+        <tr>
+            <td>IP机房信息:</td>
+            <td>@Model.Asn.AutonomousSystemOrganization</td>
+        </tr>
+        <tr>
+            <td>ASN:</td>
+            <td>@Model.Asn.AutonomousSystemNumber</td>
+        </tr>
+        <tr>
+            <td>参考地理位置:</td>
+            <td>@Model.Address</td>
+        </tr>
+        <tr>
+            <td>经纬度:</td>
+            <td>(经度:@(Model.CityInfo.Location.Longitude),纬度:@(Model.CityInfo.Location.Latitude))</td>
+        </tr>
+    </table>
 </div>
 <div class="container-fluid">
-    @if (Model.address != null && Model.address.Status == 0)
+    @if (Model.CityInfo != null)
     {
         <div id="allmap"></div>
         <script type="text/javascript" src="https://api.map.baidu.com/api?v=2.0&ak=89772e94509a9b903724e247cbc175c2"></script>
         <script>
 	    var map = new BMap.Map("allmap"); // 创建Map实例,设置地图允许的最小/大级别
 
-	    map.centerAndZoom(new BMap.Point(@(Model.address.AddressResult.Location?.Lng), @(Model.address.AddressResult.Location?.Lat)), 16);
+	    map.centerAndZoom(new BMap.Point(@(Model.CityInfo.Location.Longitude), @(Model.CityInfo.Location.Latitude)), 16);
 	    map.enableScrollWheelZoom(true);
 	    map.clearOverlays();
-	    var new_point = new BMap.Point(@(Model.address.AddressResult.Location?.Lng), @(Model.address.AddressResult.Location?.Lat));
+	    var new_point = new BMap.Point(@(Model.CityInfo.Location.Longitude), @(Model.CityInfo.Location.Latitude));
 	    var marker = new BMap.Marker(new_point); // 创建标注
 	    map.addOverlay(marker); // 将标注添加到地图中
 	    marker.setAnimation(BMAP_ANIMATION_BOUNCE); //跳动的动画

+ 9 - 5
src/Masuit.MyBlogs.Core/appsettings.json

@@ -1,15 +1,15 @@
 {
     "Logging": {
         "LogLevel": {
-            "Default": "Information"
+            "Default": "Information" // 日志级别,线上环境建议设置成Error级别
         }
     },
     "AllowedHosts": "*",
-    "Port": 5000,
+    "Port": 5000, // http监听端口
     "Https": {
         "Enabled": true, // 启用https跳转
-        "Port": 5001,
-        "CertPath": "App_Data/cert/server.pfx", // https证书
+        "Port": 5001, // https监听端口
+        "CertPath": "App_Data/cert/server.pfx", // https证书路径
         "CertPassword": "cEHlnUGu" // 证书密码
     },
     "ConnString": "Server=127.0.0.1;Port=3306;Database=MyBlogs;Uid=root;Pwd=;Charset=utf8mb4", // 数据库连接字符串
@@ -18,7 +18,7 @@
     "EmailDomainBlockList": "^\\w{1,5}@163.com,^\\w{1,5}@gmail.com,^\\w{1,5}@outlook.com,bc.com,linshiyouxiang.net,ww.com,@q.com,^.{1,12}$", // 邮箱域名黑名单,英文逗号分隔,支持正则表达式
     "UseRewriter": "NonWww", //NonWww:重定向到不带www的域名,WWW:重定向到带www的域名
     "BaiduAK": "你的BaiduAK", // 百度开放平台AppKey,用于获取IP地址信息的api
-    "TrueClientIPHeader": "CF-Connecting-IP",
+    "TrueClientIPHeader": "CF-Connecting-IP", // 若有CDN,取客户端真实IP的请求头,裸奔留空即可
     "EnableIPDirect": false, // 是否允许IP直接访问
     "MailSender": "smtp", // 为空则使用smtp发送
     "MailgunConfig": { // MailSender选项为Mailgun时本配置节生效
@@ -68,6 +68,10 @@
             "BucketName": "BucketName"
         }
     },
+    "HttpClientProxy": { // HttpClient代理设置
+        "Enabled": true,
+        "Uri": "http://127.0.0.1:7890" // 支持http模式和pac模式的代理
+    },
     "OneDrive": {
         /*获取 ClientId 与 ClientSecret
         登录Azure:https://portal.azure.com/ 或 https://portal.azure.cn/ (世纪互联)