दूरस्थ होस्ट का IP पता प्राप्त करें


136

ASP.NET में एक System.Web.HttpRequestवर्ग होता है, जिसमें ServerVariablesसंपत्ति होती है जो हमें REMOTE_ADDRसंपत्ति के मूल्य से आईपी पता प्रदान कर सकती है ।

हालाँकि, मुझे ASP.NET वेब API से दूरस्थ होस्ट का IP पता प्राप्त करने का एक समान तरीका नहीं मिला।

मैं दूरस्थ होस्ट का IP पता कैसे प्राप्त कर सकता हूं जो अनुरोध कर रहा है?

जवाबों:


189

ऐसा करना संभव है, लेकिन बहुत खोज योग्य नहीं है - आपको आने वाले अनुरोध से संपत्ति बैग का उपयोग करने की आवश्यकता है, और जिस संपत्ति तक आपको पहुंचने की आवश्यकता है वह इस बात पर निर्भर करता है कि आप IIS (वेबहोस्टेड) ​​या स्व-होस्ट के तहत वेब एपीआई का उपयोग कर रहे हैं या नहीं। नीचे दिए गए कोड से पता चलता है कि यह कैसे किया जा सकता है।

private string GetClientIp(HttpRequestMessage request)
{
    if (request.Properties.ContainsKey("MS_HttpContext"))
    {
        return ((HttpContextWrapper)request.Properties["MS_HttpContext"]).Request.UserHostAddress;
    }

    if (request.Properties.ContainsKey(RemoteEndpointMessageProperty.Name))
    {
        RemoteEndpointMessageProperty prop;
        prop = (RemoteEndpointMessageProperty)request.Properties[RemoteEndpointMessageProperty.Name];
        return prop.Address;
    }

    return null;
}

4
धन्यवाद, मैं भी इस के लिए देख रहा था। मामूली सुधार = विस्तार वर्ग: gist.github.com/2653453
माइक जेन्सन

28
WebAPI अधिकांश भाग के लिए बहुत साफ है। यह शर्म की बात है कि एक आईपी के रूप में कुछ तुच्छ के लिए इस तरह के कोड की आवश्यकता है।
टॉड

2
है RemoteEndpointMessagePropertyमें वर्ग System.ServiceModel.Channelsनाम स्थान, System.ServiceModel.dllविधानसभा? WCF से संबंधित विधानसभा नहीं है?
सलुमा

4
@ सुलामा, हां, वे हैं। ASP.NET वेब एपीआई (वर्तमान में) दो "फ्लेवर", स्व-होस्ट और वेब-होस्ट में लागू किया गया है। वेब-होस्टेड संस्करण ASP.NET के शीर्ष पर लागू किया गया है, जबकि WCF श्रोता के शीर्ष पर स्वयं-होस्ट किया गया है। ध्यान दें कि प्लेटफ़ॉर्म (ASP.NET Web API) स्वयं होस्टिंग-एग्नॉस्टिक है, इसलिए यह संभव है कि कोई व्यक्ति भविष्य में किसी अन्य होस्टिंग को लागू करेगा और होस्ट उस प्रॉपर्टी (दूरस्थ समापन बिंदु) को अलग तरीके से बताएगा।
18:25 बजे carlosfigueira

3
दुर्भाग्य से, यह काम नहीं करता है यदि आप ओवेन का उपयोग करके स्वयं-होस्ट करते हैं (जैसा कि वेब एपीआई 2 के लिए अनुशंसित है)। एक और की जरूरत है अगर वहाँ ...
निकोलाई Samteladze

74

यह समाधान ओविन का उपयोग करते हुए वेब एपीआई स्व-होस्ट को भी कवर करता है। आंशिक रूप से यहाँ से

आप में एक निजी विधि बना सकते हैं जो आपके ApiControllerआईपी ​​एपीआई को होस्ट करने पर कोई फर्क नहीं पड़ता है।

 private const string HttpContext = "MS_HttpContext";
 private const string RemoteEndpointMessage =
     "System.ServiceModel.Channels.RemoteEndpointMessageProperty";
 private const string OwinContext = "MS_OwinContext";

 private string GetClientIp(HttpRequestMessage request)
 {
       // Web-hosting
       if (request.Properties.ContainsKey(HttpContext ))
       {
            HttpContextWrapper ctx = 
                (HttpContextWrapper)request.Properties[HttpContext];
            if (ctx != null)
            {
                return ctx.Request.UserHostAddress;
            }
       }

       // Self-hosting
       if (request.Properties.ContainsKey(RemoteEndpointMessage))
       {
            RemoteEndpointMessageProperty remoteEndpoint =
                (RemoteEndpointMessageProperty)request.Properties[RemoteEndpointMessage];
            if (remoteEndpoint != null)
            {
                return remoteEndpoint.Address;
            }
        }

       // Self-hosting using Owin
       if (request.Properties.ContainsKey(OwinContext))
       {
           OwinContext owinContext = (OwinContext)request.Properties[OwinContext];
           if (owinContext != null)
           {
               return owinContext.Request.RemoteIpAddress;
           }
       }

        return null;
 }

संदर्भ आवश्यक:

  • HttpContextWrapper - System.Web.dll
  • RemoteEndpointMessageProperty - System.ServiceModel.dll
  • OwinContext - Microsoft.Owin.dll (आपके पास पहले से ही होगा यदि आप ओवेन पैकेज का उपयोग करते हैं)

इस समाधान के साथ एक छोटी समस्या यह है कि आपको सभी 3 मामलों के लिए पुस्तकालयों को लोड करना होगा जब आप वास्तव में रनटाइम के दौरान उनमें से केवल एक का उपयोग कर रहे होंगे। जैसा कि यहाँ सुझाया गया है , dynamicचर का उपयोग करके इसे दूर किया जा सकता है । आप GetClientIpAddressविस्तार के लिए विधि भी लिख सकते हैं HttpRequestMethod

using System.Net.Http;

public static class HttpRequestMessageExtensions
{
    private const string HttpContext = "MS_HttpContext";
    private const string RemoteEndpointMessage =
        "System.ServiceModel.Channels.RemoteEndpointMessageProperty";
    private const string OwinContext = "MS_OwinContext";

    public static string GetClientIpAddress(this HttpRequestMessage request)
    {
       // Web-hosting. Needs reference to System.Web.dll
       if (request.Properties.ContainsKey(HttpContext))
       {
           dynamic ctx = request.Properties[HttpContext];
           if (ctx != null)
           {
               return ctx.Request.UserHostAddress;
           }
       }

       // Self-hosting. Needs reference to System.ServiceModel.dll. 
       if (request.Properties.ContainsKey(RemoteEndpointMessage))
       {
            dynamic remoteEndpoint = request.Properties[RemoteEndpointMessage];
            if (remoteEndpoint != null)
            {
                return remoteEndpoint.Address;
            }
        }

       // Self-hosting using Owin. Needs reference to Microsoft.Owin.dll. 
       if (request.Properties.ContainsKey(OwinContext))
       {
           dynamic owinContext = request.Properties[OwinContext];
           if (owinContext != null)
           {
               return owinContext.Request.RemoteIpAddress;
           }
       }

        return null;
    }
}

अब आप इसे इस तरह से उपयोग कर सकते हैं:

public class TestController : ApiController
{
    [HttpPost]
    [ActionName("TestRemoteIp")]
    public string TestRemoteIp()
    {
        return Request.GetClientIpAddress();
    }
}

1
इस समाधान को काम करने के लिए इस नामस्थान "System.Net.Http" का उपयोग करना चाहिए। चूंकि यह विधानसभा System.Web.Http.dll पर एक वर्ग का नाम है, v5.2.2.0।
वैगनर बर्तोलिनी जूनियर

@WagnerBertolini, आपका सही है, आपको using System.Net.Http;लाइन की आवश्यकता है क्योंकि आपके विस्तार हो रहे हैं HttpRequestMessage। जब तक आपका System.Net.Httpनामस्थान में आपके विस्तार को परिभाषित नहीं कर रहा है जो बहुत ही संदिग्ध है। यह सुनिश्चित नहीं है कि यह आवश्यक है, क्योंकि यह स्वचालित रूप से किसी भी आईडीई या उत्पादकता उपकरण द्वारा जोड़ा जाएगा। तुम क्या सोचते हो?
निकोलाई सैमटेलजेड

मैं जल्दी से यहाँ एक काम खत्म करने की कोशिश कर रहा था और मुझे यह देखने में 20 मिनट का समय लगा। मैंने सिर्फ कोड की प्रतिलिपि बनाई और इसके लिए एक वर्ग बनाया, जब यह संकलित करने के तरीके नहीं दिखा रहे थे, जब मैंने वीएस पर "गो टू डेफिनिशन" का उपयोग किया तो यह मुझे मेरी कक्षा में ले गया, और मुझे समझ नहीं आ रहा था कि क्या हो रहा है, जब तक कि मैं नहीं चलूंगा दूसरे वर्ग को पाया। एक्सटेंशन एक बहुत नई विशेषता है और इसका उपयोग हर समय नहीं किया जाता है, क्योंकि, मुझे लगता है कि इस समय को बचाना एक अच्छा विचार होगा।
वैग्नर बर्तोलिनी जूनियर

1
OWIN का उपयोग करते समय, आप OWIN संदर्भ प्राप्त करने के लिए OwinHttpRequestMessageExtensions का उपयोग कर सकते हैं जैसे: request.GetOwinContext ()। Request.RemoteIpAddress
Stef Heyenrath

1
यह वास्तव में var ctx = request.roperties होना चाहिए [MsHttpContext] HttpContextWrapper के रूप में; यदि आप कास्ट करते हैं, तो आपको शून्य पर जांच करने की आवश्यकता नहीं है क्योंकि यदि कास्ट विफल रहता है, तो आपको एक अपवाद मिलता है
स्टेफ हेयानाथ

31

यदि आप वास्तव में वन-लाइनर चाहते हैं और वेब एपीआई की स्वयं-मेजबानी करने की योजना नहीं बनाते हैं:

((System.Web.HttpContextWrapper)Request.Properties["MS_HttpContext"]).Request.UserHostAddress;

13

उपरोक्त उत्तरों के लिए System.Web के संदर्भ की आवश्यकता होती है, जो संपत्ति को HttpContext या HttpContextWrapper पर लाने में सक्षम हो। यदि आप संदर्भ नहीं चाहते हैं, तो आप डायनामिक का उपयोग करके आईपी प्राप्त कर सकते हैं:

var host = ((dynamic)request.Properties["MS_HttpContext"]).Request.UserHostAddress;

-1

कार्लोसफैजीरा द्वारा प्रदान किया गया समाधान काम करता है, लेकिन टाइप-सेफ वन-लाइनर्स बेहतर हैं: अपनी कार्रवाई पद्धति में एक using System.Webतत्कालीन पहुंच जोड़ें HttpContext.Current.Request.UserHostAddress


26
-1 यह वेब एपीआई पर भरोसा नहीं किया जा सकता है क्योंकि HttpContext.Currentपूरे कार्य पाइपलाइन में सही ढंग से जारी नहीं है; चूंकि सभी अनुरोध हैंडलिंग अतुल्यकालिक है। HttpContext.Currentवेब एपीआई कोड लिखते समय लगभग हमेशा टाला जाना चाहिए।
एंड्रास जोल्तान

@ और, मैं अधिक विस्तार से जानना चाहूंगा कि HttpContext.Current का उपयोग करना क्यों बुरा है, क्या आप इसके लिए कोई मूल्यवान संसाधन जानते हैं?
17

13
हाय @Congonge; वास्तव में - जब थ्रेडिंग मुद्दा एक समस्या हो सकती है (हालांकि हमेशा सीधे नहीं अगर SynchronizationContextकार्यों के बीच सही ढंग से प्रवाहित होती है); इसके साथ सबसे बड़ा मुद्दा यह है कि यदि आपका सेवा कोड कभी भी स्वयं-होस्ट (उदाहरण के लिए परीक्षण) होने की संभावना है - HttpContext.Currentएक विशुद्ध रूप से Asp.Net निर्माण है और जब आप स्वयं होस्ट करते हैं, तो मौजूद नहीं होता है।
एंड्रास जोल्टन

प्रकार सुरक्षा सब कुछ नहीं है। यह कोड एक हार्ड-डिबग को फेंक देगा NullReferenceExceptionयदि एक थ्रेड से उपयोग किया जाता है (उदाहरण के लिए एक कार्य वेटर, आधुनिक वेब एपीआई कोड में बहुत सामान्य) या स्वयं-होस्टेड संदर्भ में। कम से कम अन्य उत्तर बस वापस आ जाएंगे null
हारून ने
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.