ฉันจะรับที่อยู่ IP ของลูกค้าใน ASP.NET CORE ได้อย่างไร


206

คุณช่วยกรุณาบอกให้ฉันทราบวิธีรับที่อยู่ IP ของลูกค้าใน ASP.NET เมื่อใช้ MVC 6 Request.ServerVariables["REMOTE_ADDR"]ไม่ทำงาน


ตัวอย่าง:httpContext.GetFeature<IHttpConnectionFeature>().RemoteIpAddress
Kiran Challa

เหตุผลการระงับไว้ที่ด้านล่างของคำถาม "มีคำตอบที่เป็นไปได้มากเกินไปหรือคำตอบที่ดีอาจยาวเกินไปสำหรับรูปแบบนี้โปรดเพิ่มรายละเอียดเพื่อ จำกัด ชุดคำตอบให้แคบลงหรือแยกปัญหาที่สามารถตอบได้ วรรคสองสามข้อ "
เควินบราวน์

12
ฉันไม่คิดว่าคำตอบนั้นนานพอ มันเป็นเรื่องง่ายที่เราทำใน MVC รุ่นเก่า ฉันเพิ่งถามว่าจะทำอย่างไรในรุ่นเบต้าล่าสุด ประการที่สองหากมีคำตอบมากมายทำไมไม่มีใครแค่ชี้ให้ฉันไปที่หนึ่งในนั้น Infact, MVC 6 เป็นรุ่นเบต้าและฉันคิดว่าพวกเขาไม่ได้อ่านคำถามอย่างถูกต้องก่อนที่จะถือมัน
eadam

แก้ไขคำถามของคุณแสดงสิ่งที่คุณได้ลองแล้วและอินพุต / เอาต์พุตที่ชัดเจน อย่าเพิ่งบ่นว่าคำถามของคุณถูกปิดโดยที่อย่างน้อยก็พยายามปรับปรุงมัน

10
โปรแกรมเมอร์เท่านั้นจากโดเมนเดียวกันควรปิดคำถาม ทุกคนที่ทำงานใน asp.net 5.0 จะรู้ว่าฉันขออะไรในเสี้ยววินาที พวกคุณที่เหลือแค่ลงโทษฉันที่โพสต์คำถามง่ายๆ
eadam

คำตอบ:


276

API ได้รับการอัปเดตแล้ว ไม่แน่ใจว่าเมื่อมันเปลี่ยนไป แต่ตาม Damien Edwardsในปลายเดือนธันวาคมคุณสามารถทำสิ่งนี้ได้:

var remoteIpAddress = request.HttpContext.Connection.RemoteIpAddress;

9
RemoteIpAddressอยู่เสมอnullสำหรับฉันเมื่อฉันเผยแพร่เว็บไซต์ของเขาบน IIS และเข้าสู่ระบบนี้ในแฟ้ม
A-Sharabiani

3
ดูเหมือนว่าปัญหาได้รับการแก้ไขใน rc 2
Jon

12
ฉันมักจะได้รับ 127.0.0.1 แม้ว่าฉันจะเชื่อมต่อจากระยะไกล
frostymarvelous

33
นี่กำลังส่งคืน ":: 1" สำหรับฉันซึ่งเป็นรูปแบบ IPv6 คนอื่นเห็น 127.0.0.1 อย่างไร
Derek Greer

4
ใครบ้างที่ได้รับที่อยู่ IP ท้องถิ่นของเซิร์ฟเวอร์ IIS ของพวกเขากลับมา?
dave317

73

ใน project.json เพิ่มการพึ่งพา:

"Microsoft.AspNetCore.HttpOverrides": "1.0.0"

ในStartup.cs, ในConfigure()วิธีการเพิ่ม:

  app.UseForwardedHeaders(new ForwardedHeadersOptions
        {
            ForwardedHeaders = ForwardedHeaders.XForwardedFor |
            ForwardedHeaders.XForwardedProto
        });  

และแน่นอนว่า:

using Microsoft.AspNetCore.HttpOverrides;

จากนั้นฉันจะได้รับ IP โดยใช้:

Request.HttpContext.Connection.RemoteIpAddress

ในกรณีของฉันเมื่อทำการดีบักใน VS ฉันได้รับ IpV6 localhost เสมอ แต่เมื่อปรับใช้บน IIS ฉันจะได้รับ IP ระยะไกลเสมอ

ลิงก์ที่มีประโยชน์: ฉันจะรับที่อยู่ IP ของลูกค้าใน ASP.NET CORE ได้อย่างไร และRemoteIpAddress นั้นจะว่างเสมอ

::1อาจจะเป็นเพราะการ:

การยกเลิกการเชื่อมต่อที่ IIS ซึ่งส่งต่อไปยัง Kestrel ซึ่งเป็นเว็บเซิร์ฟเวอร์ v.next ดังนั้นการเชื่อมต่อไปยังเว็บเซิร์ฟเวอร์นั้นมาจาก localhost ( https://stackoverflow.com/a/35442401/5326387 )


6
นี่คือคำตอบที่ถูกต้องซึ่งมีการบันทึกไว้ในเอกสารอย่างเป็นทางการเกี่ยวกับพร็อกซีย้อนกลับ: docs.microsoft.com/en-us/aspnet/core/host-and-deploy/ …
Melvyn

8
ต้องชี้ให้เห็นว่าจำเป็นต้องเพิ่ม "แอปใช้ UsForwardedHeaders ... " ก่อนแอปพลิเคชัน UseAuthentication (); บรรทัดในกรณีที่คุณใช้การ
เยื้อง

1
สิ่งนี้ทำงานได้อย่างสมบูรณ์แบบและฉันได้ทดสอบแล้วว่าใช้งานได้กับ IIS ที่โฮสต์ในพื้นที่ ทำงานได้ทั้งสองที่
ThomasCle

72

ตรรกะทางเลือกบางอย่างสามารถเพิ่มเพื่อจัดการกับการมี Load Balancer

นอกจากนี้จากการตรวจสอบX-Forwarded-Forจะมีการตั้งค่าส่วนหัวต่อไปแม้ว่าจะไม่มี Load Balancer (อาจเป็นเพราะชั้น Kestrel เพิ่มเติมหรือไม่):

public string GetRequestIP(bool tryUseXForwardHeader = true)
{
    string ip = null;

    // todo support new "Forwarded" header (2014) https://en.wikipedia.org/wiki/X-Forwarded-For

    // X-Forwarded-For (csv list):  Using the First entry in the list seems to work
    // for 99% of cases however it has been suggested that a better (although tedious)
    // approach might be to read each IP from right to left and use the first public IP.
    // http://stackoverflow.com/a/43554000/538763
    //
    if (tryUseXForwardHeader)
        ip = GetHeaderValueAs<string>("X-Forwarded-For").SplitCsv().FirstOrDefault();

    // RemoteIpAddress is always null in DNX RC1 Update1 (bug).
    if (ip.IsNullOrWhitespace() && _httpContextAccessor.HttpContext?.Connection?.RemoteIpAddress != null)
        ip = _httpContextAccessor.HttpContext.Connection.RemoteIpAddress.ToString();

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

    // _httpContextAccessor.HttpContext?.Request?.Host this is the local host.

    if (ip.IsNullOrWhitespace())
        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();   // writes out as Csv when there are multiple.

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

public static List<string> SplitCsv(this string csvList, bool nullOrWhitespaceInputReturnsNull = false)
{
    if (string.IsNullOrWhiteSpace(csvList))
        return nullOrWhitespaceInputReturnsNull ? null : new List<string>();

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

public static bool IsNullOrWhitespace(this string s)
{
    return String.IsNullOrWhiteSpace(s);
}

สมมติ_httpContextAccessorให้ผ่าน DI


2
นี่คือคำตอบที่ถูกต้อง ไม่มีวิธีการเดียวในการดึงข้อมูลที่อยู่ IP โดยเฉพาะอย่างยิ่งเมื่อแอปของคุณอยู่หลัง Nginx ตัวโหลดบาลานซ์หรืออะไรทำนองนั้น ขอบคุณ!
Feu

ชนิด @feu เนื่องจาก AspNetCore สามารถแทนที่คุณสมบัติ RemoteIpAddress ด้วยส่วนหัวเช่น X-Forwarded-For
Mark Lopez

@crokusek ... พยายามปรับแก้ปัญหาของคุณ แต่ VS บังคับให้ฉันเข้าคลาส encapsulating รหัสนี้คงที่ คุณมีรหัสนี้ในโครงการแอปบนเว็บหรือในไลบรารีคลาสในโซลูชันหรือไม่
dinotom

2 วิธีแรกควรอยู่ในอินสแตนซ์ที่มี __httpContextAccessor (หรือปรับเปลี่ยน) เมธอดสตริง 2 ที่สองถูกดึงจากคลาสส่วนขยายแบบสแตติกที่แยกต่างหาก
crokusek

นี่เป็นทางออกที่ดีโดยเฉพาะเมื่อแอปของคุณใช้ Kestrel และโฮสต์กับ Nginx บน Linux
ทิโมธี Macharia

16

คุณสามารถใช้IHttpConnectionFeatureเพื่อรับข้อมูลนี้

var remoteIpAddress = httpContext.GetFeature<IHttpConnectionFeature>()?.RemoteIpAddress;

ขอบคุณสำหรับคำตอบ!
eadam

2
ใช้กับโฮสติ้ง Kestrel ได้หรือไม่ ในการสาธิตของฉันเสมอhttpContext.GetFeature<IHttpConnectionFeature>() null
Jerry Bian

2
@JerryBian ตามเอกสารนี้: github.com/aspnet/Docs/blob/master/aspnet/fundamentals/… , IHttpConnectionFeature ยังไม่ได้รับการสนับสนุนใน Kestrel (ยัง)
qbik

@JerryBian ตอนนี้
David Peden

ต้องเลิกใช้แล้ว - รุ่น @feradz ใช้งานได้สำหรับฉันใน RC-1
fiat

12
var remoteIpAddress = HttpContext.Features.Get<IHttpConnectionFeature>()?.RemoteIpAddress;

6
ซับซ้อนเกินไป MVC HttpContext.Connection.RemoteIpAddressแล้วเรียกว่าภายในและทำให้มันอยู่ภายใต้
Fred

@Fred - เวอร์ชันของคุณจะคืนค่า null ให้ฉันใน RC-1 - IIS และ Kestrel
fiat

7

สิ่งนี้ใช้ได้สำหรับฉัน (DotNetCore 2.1)

[HttpGet]
public string Get() 
{
    var remoteIpAddress = HttpContext.Connection.RemoteIpAddress;
    return remoteIpAddress.ToString();
}

7

ใน ASP.NET 2.1 ใน StartUp.cs เพิ่มบริการนี้:

services.AddHttpContextAccessor();
services.TryAddSingleton<IActionContextAccessor, ActionContextAccessor>();

จากนั้นทำ 3 ขั้นตอน:

  1. กำหนดตัวแปรในตัวควบคุม MVC ของคุณ

    private IHttpContextAccessor _accessor;
  2. DI เข้าไปในคอนสตรัคเตอร์ของคอนโทรลเลอร์

    public SomeController(IHttpContextAccessor accessor)
    {
        _accessor = accessor;
    }
  3. ดึงที่อยู่ IP

    _accessor.HttpContext.Connection.RemoteIpAddress.ToString()

นี่คือวิธีที่มันทำ


2
สิ่งนี้ทำให้ฉัน :: 1 Asp.Net Core 2.2. บน localhost
เตียน

::1เป็น localhost ใน IPv6 จำนวน IPv4 ที่เทียบเท่า127.0.0.1
Andy

3

ในกรณีของฉันฉันมี DotNet Core 2.2 Web App ที่ทำงานบน DigitalOcean พร้อม Docker และ nginx เป็น reverse proxy ด้วยรหัสนี้ใน Startup.cs ฉันสามารถรับ IP ของไคลเอ็นต์ได้

app.UseForwardedHeaders(new ForwardedHeadersOptions
        {
            ForwardedHeaders = ForwardedHeaders.All,
            RequireHeaderSymmetry = false,
            ForwardLimit = null,
            KnownNetworks = { new IPNetwork(IPAddress.Parse("::ffff:172.17.0.1"), 104) }
        });

:: ffff: 172.17.0.1 เป็น IP ที่ฉันได้รับก่อนใช้

Request.HttpContext.Connection.RemoteIpAddress.ToString();

2

ครั้งแรกใน. Net Core 1.0 เพิ่มusing Microsoft.AspNetCore.Http.Features;ไปยังตัวควบคุมจากนั้นภายในวิธีการที่เกี่ยวข้อง:

var ip = HttpContext.Features.Get<IHttpConnectionFeature>()?.RemoteIpAddress?.ToString();

ฉันอ่านคำตอบอื่น ๆ ที่ล้มเหลวในการรวบรวมเพราะใช้ httpContext ตัวพิมพ์เล็กทำให้ VS เพิ่มขึ้นโดยใช้ Microsoft.AspNetCore.Http แทนที่จะใช้อย่างเหมาะสมหรือกับ HttpContext (คอมไพเลอร์ก็ทำให้เข้าใจผิด)


2

รับ ipaddress และชื่อโฮสต์ใน. net core

ใส่รหัสนี้ในคอนโทรลเลอร์

ทำตามขั้นตอนเหล่านี้:

var addlist = Dns.GetHostEntry(Dns.GetHostName());
string GetHostName = addlist.HostName.ToString();
string GetIPV6 = addlist.AddressList[0].ToString();
string GetIPV4 = addlist.AddressList[1].ToString();

2

ฉันพบว่าบางส่วนของคุณพบว่าที่อยู่ IP ที่คุณได้รับคือ ::: 1 หรือ 0.0.0.1

ปัญหานี้เป็นปัญหาเนื่องจากคุณพยายามรับ IP จากเครื่องของคุณเองและความสับสนของ C # ที่พยายามส่งคืน IPv6

ดังนั้นฉันจึงใช้คำตอบจาก @Johna (คนhttps://stackoverflow.com/a/41335701/812720 ) และ @ David ( https://stackoverflow.com/a/8597351/812720 ) ขอบคุณพวกเขา!

และที่นี่เพื่อแก้ปัญหา:

  1. เพิ่ม Microsoft.AspNetCore.HttpOverrides Package ในเอกสารอ้างอิงของคุณ (การอ้างอิง / แพ็คเกจ)

  2. เพิ่มบรรทัดนี้ใน Startup.cs

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        // your current code
    
        // start code to add
        // to get ip address
        app.UseForwardedHeaders(new ForwardedHeadersOptions
        {
        ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
        });
        // end code to add
    
    }
  3. ในการรับ IPAddress ให้ใช้รหัสนี้ใน Controller.cs ใด ๆ ของคุณ

    IPAddress remoteIpAddress = Request.HttpContext.Connection.RemoteIpAddress;
    string result = "";
    if (remoteIpAddress != null)
    {
        // If we got an IPV6 address, then we need to ask the network for the IPV4 address 
        // This usually only happens when the browser is on the same machine as the server.
        if (remoteIpAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6)
        {
            remoteIpAddress = System.Net.Dns.GetHostEntry(remoteIpAddress).AddressList
    .First(x => x.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork);
        }
        result = remoteIpAddress.ToString();
    }

และตอนนี้คุณสามารถรับที่อยู่ IPv4 จากremoteIpAddressหรือผลลัพธ์


1

ลองนี้

var host = Dns.GetHostEntry(Dns.GetHostName());
        foreach (var ip in host.AddressList)
        {
            if (ip.AddressFamily == AddressFamily.InterNetwork)
            {
                 ipAddress = ip.ToString();
            }
        }

0

การทำงาน.NET core(3.1.4) ที่IISอยู่ด้านหลังตัวโหลดบาลานซ์ไม่ทำงานกับโซลูชันที่แนะนำอื่น ๆ

การอ่านX-Forwarded-Forส่วนหัวด้วยตนเองทำ

IPAddress ip;
var headers = Request.Headers.ToList();
if (headers.Exists((kvp) => kvp.Key == "X-Forwarded-For"))
{
    // when running behind a load balancer you can expect this header
    var header = headers.First((kvp) => kvp.Key == "X-Forwarded-For").Value.ToString();
    ip = IPAddress.Parse(header);
}
else
{
    // this will always have a value (running locally in development won't have the header)
    ip = Request.HttpContext.Connection.RemoteIpAddress;
}

ฉันทำงานด้วยตนเองที่มีแพคเกจที่ใช้มัดโฮสติ้ง


0

ใช้ ASP.NET Core 2.1 อยู่หลัง Traefik reverse Proxy บน Ubuntu ฉันต้องตั้งค่า IP ของเกตเวย์KnownProxiesหลังจากติดตั้งMicrosoft.AspNetCore.HttpOverridesแพ็คเกจอย่างเป็นทางการ

        var forwardedOptions = new ForwardedHeadersOptions {
            ForwardedHeaders = ForwardedHeaders.XForwardedFor,
        };
        forwardedOptions.KnownProxies.Add(IPAddress.Parse("192.168.3.1"));
        app.UseForwardedHeaders(forwardedOptions);

ตามเอกสารอธิบายสิ่งนี้จำเป็นหาก reverse proxy ไม่ได้ทำงานบน localhost The docker-compose.ymlof Traefik ได้กำหนดที่อยู่ IP แบบคงที่:

networks:
  my-docker-network:
    ipv4_address: 192.168.3.2

หรือควรเพียงพอที่จะตรวจสอบให้แน่ใจว่ามีการกำหนดเครือข่ายที่รู้จักที่นี่เพื่อระบุเกตเวย์ใน. NET Core

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.