Pārlūkot izejas kodu

优化ip信息获取

懒得勤快 5 gadi atpakaļ
vecāks
revīzija
6076c9d956

BIN
src/Masuit.MyBlogs.Core/App_Data/GeoLite2-ASN.mmdb


BIN
src/Masuit.MyBlogs.Core/App_Data/GeoLite2-City.mmdb


BIN
src/Masuit.MyBlogs.Core/App_Data/ip2region.db


+ 18 - 12
src/Masuit.MyBlogs.Core/Common/CommonHelper.cs

@@ -8,10 +8,8 @@ using Masuit.Tools.Media;
 using MaxMind.GeoIP2;
 using MaxMind.GeoIP2.Exceptions;
 using MaxMind.GeoIP2.Responses;
-using Microsoft.AspNetCore.Http;
 using Microsoft.EntityFrameworkCore.Internal;
 using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Net.Http.Headers;
 using Polly;
 using System;
 using System.Collections.Concurrent;
@@ -143,7 +141,17 @@ namespace Masuit.MyBlogs.Core.Common
 
         private static readonly DbSearcher IPSearcher = new DbSearcher(Path.Combine(AppContext.BaseDirectory + "App_Data", "ip2region.db"));
         public static readonly DatabaseReader MaxmindReader = new DatabaseReader(Path.Combine(AppContext.BaseDirectory + "App_Data", "GeoLite2-City.mmdb"));
-        public static readonly DatabaseReader MaxmindAsnReader = new DatabaseReader(Path.Combine(AppContext.BaseDirectory + "App_Data", "GeoLite2-ASN.mmdb"));
+        private static readonly DatabaseReader MaxmindAsnReader = new DatabaseReader(Path.Combine(AppContext.BaseDirectory + "App_Data", "GeoLite2-ASN.mmdb"));
+
+        public static AsnResponse GetIPAsn(this string ip)
+        {
+            return Policy<AsnResponse>.Handle<AddressNotFoundException>().Fallback(new AsnResponse()).Execute(() => MaxmindAsnReader.Asn(ip));
+        }
+
+        public static AsnResponse GetIPAsn(this IPAddress ip)
+        {
+            return Policy<AsnResponse>.Handle<AddressNotFoundException>().Fallback(new AsnResponse()).Execute(() => MaxmindAsnReader.Asn(ip));
+        }
 
         public static string GetIPLocation(this string ips)
         {
@@ -168,7 +176,7 @@ namespace Masuit.MyBlogs.Core.Common
                     var parts = IPSearcher.MemorySearch(ip.ToString())?.Region.Split('|');
                     if (parts != null)
                     {
-                        var asn = Policy<AsnResponse>.Handle<AddressNotFoundException>().Fallback(new AsnResponse()).Execute(() => MaxmindAsnReader.Asn(ip));
+                        var asn = GetIPAsn(ip);
                         var network = parts[^1] == "0" ? asn.AutonomousSystemOrganization : parts[^1];
                         var location = parts[..^1].Where(s => s != "0").Distinct().Join("");
                         return (location, network + $"(AS{asn.AutonomousSystemNumber})");
@@ -177,11 +185,16 @@ namespace Masuit.MyBlogs.Core.Common
                     goto default;
                 default:
                     var cityResp = Policy<CityResponse>.Handle<AddressNotFoundException>().Fallback(new CityResponse()).Execute(() => MaxmindReader.City(ip));
-                    var asnResp = Policy<AsnResponse>.Handle<AddressNotFoundException>().Fallback(new AsnResponse()).Execute(() => MaxmindAsnReader.Asn(ip));
+                    var asnResp = GetIPAsn(ip);
                     return (cityResp.Country.Names.GetValueOrDefault("zh-CN") + cityResp.City.Names.GetValueOrDefault("zh-CN"), asnResp.AutonomousSystemOrganization + $"(AS{asnResp.AutonomousSystemNumber})");
             }
         }
 
+        /// <summary>
+        /// 获取ip所在时区
+        /// </summary>
+        /// <param name="ip"></param>
+        /// <returns></returns>
         public static string GetClientTimeZone(this IPAddress ip)
         {
             switch (ip.AddressFamily)
@@ -218,13 +231,6 @@ namespace Masuit.MyBlogs.Core.Common
             RedisHelper.Expire($"Email:{DateTime.Now:yyyyMMdd}", 86400);
         }
 
-        /// <summary>
-        /// 是否是机器人访问
-        /// </summary>
-        /// <param name="req"></param>
-        /// <returns></returns>
-        public static bool IsRobot(this HttpRequest req) => UserAgent.Parse(req.Headers[HeaderNames.UserAgent].ToString()).IsRobot;
-
         /// <summary>
         /// 清理html的img标签的除src之外的其他属性
         /// </summary>

+ 55 - 0
src/Masuit.MyBlogs.Core/Common/HttpContextExtension.cs

@@ -0,0 +1,55 @@
+using Masuit.MyBlogs.Core.Configs;
+using Masuit.Tools;
+using MaxMind.GeoIP2.Responses;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Net.Http.Headers;
+
+namespace Masuit.MyBlogs.Core.Common
+{
+    public static class HttpContextExtension
+    {
+        /// <summary>
+        /// 地理位置信息
+        /// </summary>
+        /// <param name="request"></param>
+        /// <returns></returns>
+        public static string Location(this HttpRequest request)
+        {
+            return (string)request.HttpContext.Items.GetOrAdd("ip.location", () => request.HttpContext.GetTrueIP().GetIPLocation());
+        }
+
+        /// <summary>
+        /// asn信息
+        /// </summary>
+        /// <param name="request"></param>
+        /// <returns></returns>
+        public static AsnResponse Asn(this HttpRequest request)
+        {
+            return (AsnResponse)request.HttpContext.Items.GetOrAdd("ip.asn", () => request.HttpContext.GetTrueIP().GetIPAsn());
+        }
+
+        /// <summary>
+        /// 获取真实客户端ip
+        /// </summary>
+        /// <param name="context"></param>
+        /// <returns></returns>
+        public static string GetTrueIP(this HttpContext context)
+        {
+            var ip = context.Connection.RemoteIpAddress.ToString();
+            var trueip = context.Request.Headers[AppConfig.TrueClientIPHeader].ToString();
+            if (!string.IsNullOrEmpty(trueip) && ip != trueip)
+            {
+                ip = trueip;
+            }
+
+            return ip;
+        }
+
+        /// <summary>
+        /// 是否是机器人访问
+        /// </summary>
+        /// <param name="req"></param>
+        /// <returns></returns>
+        public static bool IsRobot(this HttpRequest req) => UserAgent.Parse(req.Headers[HeaderNames.UserAgent].ToString()).IsRobot;
+    }
+}

+ 1 - 13
src/Masuit.MyBlogs.Core/Controllers/BaseController.cs

@@ -47,19 +47,7 @@ namespace Masuit.MyBlogs.Core.Controllers
         /// <summary>
         /// 客户端的真实IP
         /// </summary>
-        public string ClientIP
-        {
-            get
-            {
-                var ip = HttpContext.Connection.RemoteIpAddress.ToString();
-                var trueip = Request.Headers[AppConfig.TrueClientIPHeader].ToString();
-                if (!string.IsNullOrEmpty(trueip) && ip != trueip)
-                {
-                    ip = trueip;
-                }
-                return ip;
-            }
-        }
+        public string ClientIP => HttpContext.GetTrueIP();
 
         /// <summary>
         /// 普通访客是否token合法

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

@@ -89,7 +89,7 @@ namespace Masuit.MyBlogs.Core.Controllers
             comment.Content = dto.Content.HtmlSantinizerStandard().ClearImgAttributes();
             comment.Browser = dto.Browser ?? Request.Headers[HeaderNames.UserAgent];
             comment.IP = ClientIP;
-            comment.Location = comment.IP.GetIPLocation();
+            comment.Location = Request.Location();
             comment = CommentService.AddEntitySaved(comment);
             if (comment == null)
             {

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

@@ -162,7 +162,7 @@ namespace Masuit.MyBlogs.Core.Controllers
 
         private void CheckPermission(PagedList<PostDto> posts)
         {
-            var location = ClientIP.GetIPLocation() + "|" + Request.Headers[HeaderNames.UserAgent];
+            var location = Request.Location() + "|" + Request.Headers[HeaderNames.UserAgent];
             posts.Data.RemoveAll(p => p.LimitMode switch
             {
                 PostLimitMode.AllowRegion => !location.Contains(p.Regions.Split(',', StringSplitOptions.RemoveEmptyEntries)) && !CurrentUser.IsAdmin && !VisitorTokenValid && !Request.IsRobot(),

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

@@ -159,7 +159,7 @@ namespace Masuit.MyBlogs.Core.Controllers
             msg.Content = dto.Content.HtmlSantinizerStandard().ClearImgAttributes();
             msg.Browser = dto.Browser ?? Request.Headers[HeaderNames.UserAgent];
             msg.IP = ClientIP;
-            msg.Location = msg.IP.GetIPLocation();
+            msg.Location = Request.Location();
             msg = LeaveMessageService.AddEntitySaved(msg);
             if (msg == null)
             {

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

@@ -103,7 +103,7 @@ namespace Masuit.MyBlogs.Core.Controllers
 
         private void CheckPermission(Post post)
         {
-            var location = ClientIP.GetIPLocation() + "|" + Request.Headers[HeaderNames.UserAgent];
+            var location = Request.Location() + "|" + Request.Headers[HeaderNames.UserAgent];
             switch (post.LimitMode)
             {
                 case PostLimitMode.AllowRegion:

+ 9 - 8
src/Masuit.MyBlogs.Core/Controllers/ToolsController.cs

@@ -5,6 +5,7 @@ using Masuit.Tools.Core.Net;
 using Masuit.Tools.Core.Validator;
 using Masuit.Tools.Models;
 using MaxMind.GeoIP2.Exceptions;
+using MaxMind.GeoIP2.Responses;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
 using Newtonsoft.Json;
@@ -13,7 +14,6 @@ using System;
 using System.Net.Http;
 using System.Threading.Tasks;
 using TimeZoneConverter;
-using Location = MaxMind.GeoIP2.Model.Location;
 
 #if DEBUG
 #endif
@@ -52,7 +52,8 @@ namespace Masuit.MyBlogs.Core.Controllers
             }
 
             ViewBag.IP = ip;
-            var location = Policy<Location>.Handle<AddressNotFoundException>().Fallback(() => new Location()).Execute(() => CommonHelper.MaxmindReader.City(ip).Location);
+            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()
             {
                 Status = 0,
@@ -60,23 +61,23 @@ namespace Masuit.MyBlogs.Core.Controllers
                 {
                     AddressComponent = new AddressComponent(),
                     FormattedAddress = ip.GetIPLocation(),
-                    Location = new Tools.Models.Location()
+                    Location = new Location()
                     {
-                        Lng = location.Longitude ?? 0,
-                        Lat = location.Latitude ?? 0
+                        Lng = location.Location.Longitude ?? 0,
+                        Lat = location.Location.Latitude ?? 0
                     }
                 }
             };
             address.AddressResult.Pois.Add(new Pois
             {
-                AddressDetail = $"{ip.GetIPLocation()}(UTC{TZConvert.GetTimeZoneInfo(location.TimeZone ?? "Asia/Shanghai").BaseUtcOffset.Hours:+#;-#;0},本地数据库)"
+                AddressDetail = $"{ip.GetIPLocation()}(UTC{TZConvert.GetTimeZoneInfo(location.Location.TimeZone ?? "Asia/Shanghai").BaseUtcOffset.Hours:+#;-#;0},本地数据库)"
             });
             if (Request.Method.Equals(HttpMethods.Get))
             {
-                return View(address);
+                return View((address, asn));
             }
 
-            return Json(address);
+            return Json(new { address, asn });
         }
 
         /// <summary>

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

@@ -30,13 +30,7 @@ namespace Masuit.MyBlogs.Core.Extensions.Firewall
         public override void OnActionExecuting(ActionExecutingContext context)
         {
             var request = context.HttpContext.Request;
-            var ip = context.HttpContext.Connection.RemoteIpAddress.ToString();
-            var trueip = request.Headers[AppConfig.TrueClientIPHeader].ToString();
-            if (!string.IsNullOrEmpty(trueip) && ip != trueip)
-            {
-                ip = trueip;
-            }
-
+            var ip = context.HttpContext.GetTrueIP();
             var tokenValid = request.Cookies["Email"].MDString3(AppConfig.BaiduAK).Equals(request.Cookies["FullAccessToken"]);
             if (ip.IsDenyIpAddress() && !tokenValid)
             {

+ 3 - 2
src/Masuit.MyBlogs.Core/Extensions/Firewall/RequestInterceptMiddleware.cs

@@ -42,8 +42,9 @@ namespace Masuit.MyBlogs.Core.Extensions.Firewall
                 context.Response.StatusCode = 404;
                 return;
             }
-
-            var ip = context.Connection.RemoteIpAddress.ToString();
+            var ip = context.GetTrueIP();
+            context.Items.AddOrUpdate("ip.asn", ip.GetIPAsn());
+            context.Items.AddOrUpdate("ip.location", ip.GetIPLocation());
             var path = HttpUtility.UrlDecode(request.Path + request.QueryString, Encoding.UTF8);
             var requestUrl = HttpUtility.UrlDecode(request.Scheme + "://" + request.Host + path);
             var match = Regex.Match(path ?? "", CommonHelper.BanRegex);

+ 25 - 9
src/Masuit.MyBlogs.Core/Views/Tools/GetIPInfo.cshtml

@@ -1,5 +1,5 @@
 @using Masuit.Tools.Models
-@model PhysicsAddress
+@model (PhysicsAddress address, MaxMind.GeoIP2.Responses.AsnResponse asn)
 @{
     ViewBag.Title = "获取IP地址详细地理位置信息";
     Layout = "~/Views/Shared/_Layout.cshtml";
@@ -32,23 +32,39 @@
             </span>
         </div>
     </form>
-    @if (Model != null && Model.Status == 0)
+    @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?.ToString()</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.AddressResult.FormattedAddress</td>
+                <td>@Model.address.AddressResult.FormattedAddress</td>
             </tr>
             <tr>
                 <td>标志性商业街:</td>
-                <td>@Model.AddressResult.Business</td>
+                <td>@Model.address.AddressResult.Business</td>
             </tr>
             <tr>
                 <td>经纬度:</td>
-                <td>(经度:@(Model.AddressResult.Location?.Lng),纬度:@(Model.AddressResult.Location?.Lat))</td>
+                <td>(经度:@(Model.address.AddressResult.Location?.Lng),纬度:@(Model.address.AddressResult.Location?.Lat))</td>
             </tr>
-            @foreach (Pois poi in Model.AddressResult.Pois)
+            @foreach (Pois poi in Model.address.AddressResult.Pois)
             {
                 <tr>
                     <td>参考地理位置@(++count):</td>
@@ -64,17 +80,17 @@
     }
 </div>
 <div class="container-fluid">
-    @if (Model != null && Model.Status == 0)
+    @if (Model.address != null && Model.address.Status == 0)
     {
         <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.AddressResult.Location?.Lng), @(Model.AddressResult.Location?.Lat)), 16);
+	    map.centerAndZoom(new BMap.Point(@(Model.address.AddressResult.Location?.Lng), @(Model.address.AddressResult.Location?.Lat)), 16);
 	    map.enableScrollWheelZoom(true);
 	    map.clearOverlays();
-	    var new_point = new BMap.Point(@(Model.AddressResult.Location?.Lng), @(Model.AddressResult.Location?.Lat));
+	    var new_point = new BMap.Point(@(Model.address.AddressResult.Location?.Lng), @(Model.address.AddressResult.Location?.Lat));
 	    var marker = new BMap.Marker(new_point); // 创建标注
 	    map.addOverlay(marker); // 将标注添加到地图中
 	    marker.setAnimation(BMAP_ANIMATION_BOUNCE); //跳动的动画