Get client IP address for WCF, post operation
Asked Answered
O

1

12

I am trying to determine the client's IP address following this link: http://www.danrigsby.com/blog/index.php/2008/05/21/get-the-clients-address-in-wcf/

In .Net 3.0 there was not a reliable way to obtain the address of the client connecting to a WCF service. In .Net 3.5 a new property was introduced called RemoteEndpointMessageProperty. This property gives you the IP address and port that the client connection came into the service on. Obtaining the this information is pretty straight forward. Just pull it from the IncomingMessageProperties of the current OperationContext by the RemoteEndpointMessageProperty.Name and access the Address and Port properties.

> [ServiceContract] public interface IMyService {
>     [OperationContract]
>     string GetAddressAsString(); }
> 
> public class MyService : IMyService {
>     public string GetAddressAsString()
>     {
>         RemoteEndpointMessageProperty clientEndpoint =
>             OperationContext.Current.IncomingMessageProperties[
>             RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
> 
>         return String.Format(
>             "{0}:{1}",
>             clientEndpoint.Address, clientEndpoint.Port);
>     } } 

Things to note:

  1. This property only works on http and tcp transports. On all other transports such as MSMQ and NamedPipes, this property will not be available.
  2. The address and port are reported by the socket or http.sys of the service’s machine. So if the client came in over a VPN or some other proxy that modified the address, that new address will be represented instead of the client’s local address. This is desirable and important because this is the address and port that the service sees the client as, not as the client sees itself as. This also means that there could be some spoofing going on. A client or something in between the client and server could spoof an address. So, do not use the address or port for any security decisions unless you add in some other custom checking mechanisms.
  3. If you are using duplexing on your service, then not only will the service have this property populated for the client, but the client will also have this property populated for the service for each call from that service.

I have operationContracts of WebInvoke/Post and WebGet. The code works when the client request is a WebGet. But when the client request is a WebInvoke, I will get the WCF host IP. Any solution? Thanks.

Here is the interface

[OperationContract]
[WebGet(UriTemplate = RestTemplate.hello_get)]
Stream hello_get();

[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = RestTemplate.hello_post)]
Stream hello_post();

// Code for getting IP
private string getClientIP()
{
    //WebOperationContext webContext = WebOperationContext.Current;

    OperationContext context = OperationContext.Current;

    MessageProperties messageProperties = context.IncomingMessageProperties;

    RemoteEndpointMessageProperty endpointProperty =

    messageProperties[RemoteEndpointMessageProperty.Name]

    as RemoteEndpointMessageProperty;
    return endpointProperty.Address;
}

public Stream hello_get()
{
    string ip = getClientIP();
    ...
}

public Stream hello_post()
{
    string ip = getClientIP();
    ...
} 
Occasionalism answered 27/8, 2010 at 0:13 Comment(8)
You may want to show what you have tried that hasn't worked.Opt
I agree with James. I don't see why this wouldn't work for a WebInvoke. Can you provide some code (and configuration) so we can how you're handling it?Tenotomy
Thanks. I have added some code as show above.Occasionalism
If this doesn't work you should create simple example which reproduces issue and post it to Microsoft Connect. For me this is a bug because there is no reason why GET should work and POST not.Sweptback
The link is dead, so its hard to reference what the code is suppose to do now.Mcglynn
Did you check by enabling asp.net compatibility. Also, you will have to check if there is any redirection happening in the course of processing this request, in kind of a load balancing scenario.Postexilian
You may need to have a look at this #5312184Crimpy
is there a any firewall?Saffier
C
-1

Have you tried using the HttpContext? It's not available in all WCF modes but this could work depending on your environment:

if (HttpContext.Current != null)
            {
                Trace.WriteLine(
                    "Who's calling? IP address: '{0}', Name: '{1}', User Agent: '{2}', URL: '{3}'.",
                    HttpContext.Current.Request.UserHostAddress, HttpContext.Current.Request.UserHostName,
                    HttpContext.Current.Request.UserAgent, HttpContext.Current.Request.Url);
            }
Chronogram answered 17/8, 2014 at 19:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.