Asp.Net Core 获取请求端IP地址

Asp.Net Core 获取请求端IP地址

老增 1,042 2021-05-06

数据来源

主要考虑几种情况:

  1. Nginx 转发过来. 考虑解析 X-Forwarded-For 或者 X-Real-IP 请求头, 具体可以根据实际情况取舍, 也可以两个都解析 (需要nginx做相应的配置)
  2. 直接请求到 Kestrel. 可从 HttpContext.Connection.RemoteIpAddress 字段中读取出来.
  3. 在没有做其他额外配置的情况下, 代理服务器(如nginx, apache)中会记录 REMOTE_ADDR 请求头信息, 表示直接请求到这里的客户端IP, 这中间也可能是某个中转的服务器.

示例代码

注入: IHttpContextAccessor 由 .NetCore 依赖注入

using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Octopus.TaskUrl.Api
{
    public class RequestIpHelper
    {
        private readonly IHttpContextAccessor _httpContextAccessor;
        public RequestIpHelper(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
        }

        public string GetRequestIP()
        {
            string ip = SplitCsv(GetHeaderValueAs<string>("X-Forwarded-For")).FirstOrDefault();

            if(string.IsNullOrWhiteSpace(ip))
                ip = SplitCsv(GetHeaderValueAs<string>("X-Real-IP")).FirstOrDefault();

            if (string.IsNullOrWhiteSpace(ip) && _httpContextAccessor.HttpContext?.Connection?.RemoteIpAddress != null)
                ip = _httpContextAccessor.HttpContext.Connection.RemoteIpAddress.ToString();

            if (string.IsNullOrWhiteSpace(ip))
                ip = GetHeaderValueAs<string>("REMOTE_ADDR");

            if (string.IsNullOrWhiteSpace(ip))
                throw new Exception("Unable to determine caller's IP.");

            return ip;
        }

        public T GetHeaderValueAs<T>(string headerName)
        {
            StringValues values;

            if (_httpContextAccessor.HttpContext?.Request?.Headers?.TryGetValue(headerName, out values) ?? false)
            {
                string rawValues = values.ToString();

                if (!string.IsNullOrWhiteSpace(rawValues))
                    return (T)Convert.ChangeType(values.ToString(), typeof(T));
            }

            return default;
        }

        public static List<string> SplitCsv(string csvList)
        {
            if (string.IsNullOrWhiteSpace(csvList))
                return new List<string>();

            return csvList
                .TrimEnd(',')
                .Split(',')
                .AsEnumerable<string>()
                .Select(s => s.Trim())
                .ToList();
        }
    }
}


# dotnet