Is it possible to override the UserHostAddress property of the HttpRequest class? - c#

I have a situation where I need to put my application behind a proxy server, this causes all the request's that are coming to my application to have the same set of IP addresses used by the proxy servers. However the Proxy server provides the real IP address of the requestor in a custom header, that I can use through my application so I can know the real IP address of the requestor. This is mainly used for logging and tracking. Is there a way I can have the UserHostAddress property return the value from this custom header? This would save a lot of work, because this property referenced about a few hundred time.

It's not possible to change the behavior of the UserHostAddress property, however what you can do is add an extension method to the Request class (something like GetRealUserHostAddress()) and just do a global replace on UserHostAddress -> GetRealUserHostAddress() to rapidly sort out all the instances of it in your solution.
public static string GetRealUserHostAddress(this HttpRequestBase request)
{
return request.Headers["HeaderName"] ?? request.UserHostAddress;
}

If you are saying that the proxy returns the real ip address of the client making the request, you don't need to use the UserHostAddress to read it; you can simply read the header directly:
string realIP = HttpContext.Request.Headers["actual_header_key"];

No, it's not possible. You can read the custom header and place in the request context and use that later.

Related

How to get the request URI of a RESTful webservice

I have a webservice that is used under several different websites and want to know which of the sites the request came through (and return different things depending on that data). How do I do this?
I have a website, example.com, that has one webservice in /webservice.svc . When the client comes to this site via http://client1.example.com/webservice.svc/hello I want to say "hello, client1!" and when they come through http://client2.example.com/webservice.svc/hello it should say "hello, client2!".
So client1 or client2 depending on subhost (or application directory)
Ended up getting this done with HttpContext.Current.Request.Url.ToString();
It too returned "Object reference not set to an instance of an object" originally when I tried, but found that setting [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] before my class declaration as well as in web.config did the trick and allowed access to the variables I wanted.
Assuming you are using WCF, you can try:
System.ServiceModel.Web.WebOperationContext.Current.IncomingRequest.Headers["Referer"]
The result will in your example be http://client1.example.com/webservice.svc/hello or http://client2.example.com/webservice.svc/hello. You can then parse that string for presence of client1 or client2.
You may want to check for nulls.

How to bind a WCF Http client to a specific outbound IPAddress before making the request

I want my request to go out through a specific IP Addresses. Is there a way to do that in WCF. The explanation of why I need this is a little long winded so i'd rather not get into that.
Here is sample code
string ipAddress = "192.168.0.32";
IService service;
ChannelFactory<IOmlService> factory = new ChannelFactory<IService>(new BasicHttpBinding(), new EndpointAddress("http://" + IPAddress + ":6996/IService"));
service = factory.CreateChannel();
service.Test();
Here is an example scenario to explain exactly what i'm looking for. Let's say I have two IPs on my machine (192.168.0.30 and 192.168.0.31). Both of them can hit 192.168.0.32. If i run this code now, it will hit the IP (.32) from any of my IPs (.30 or .31). How can i force it to go through a specific IP of mine (say .30). Is there any way to do that using WCF?
The answer to the question is that it cannot be done. Here is the answer from a Microsoft MVP
So you want to let the client-side machine proactively select one of the network adpater interface(installed on it) to send out the WCF requests? I'm afraid this is out of WCF's control since WCF only focus on the following addresses:
** when behave as a host, we can choose to bind to a specific hostname/address to listen for client requests
** when behave as a client, we can choose the destination address/hostname to send request to.
Are you trying to make something similar to IP-Sec on the Server so it only accepts request from specific IP addresses?
In this case, you need to implement IEndpointBehavior and IDispatchMessageInspector and:
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
RemoteEndpointMessageProperty remoteAddress =
(OperationContext.Current.IncomingMessageProperties[RemoteEndpointMessageProperty.Name] as
RemoteEndpointMessageProperty);
// validate ip here
return null;
}
It seems to me that your problem should be solved by setting of an additional rote in the routing table. Try do following from the Command Prompt started with administrative rights:
route add 192.168.0.32 mask 255.255.255.255 192.168.175.30
If you want to save the route add -p switch additionally.

Differentiate between client app and browser in ASMX Web Service?

This is a follow-up to Choosing a Connection String based on kind of request for which I got no answer and what I thought worked doesn't.
I have a webservice that needs to choose a specific connection string based on the user calling it from a browser or from a client application.
I tried:
HttpContext.Current != null? ConnectionStrings["Website"].ConnectionString : ConnectionStrings["Client"].ConnectionString
but realized that at some point even if I'm using the client application, there is some HttpContext (if someone can explain why it'd be great) but the Browser field under Request is "Unknown". So, then I tried:
if ( HttpContext.Current != null )
{
if ( HttpContext.Current.Request.Browser != "Unknown" )
{
//browser connection string here
}
else
//client app connection string here
}
else
//client app connection string here
This worked wonders when debugging, but on testing environment it still points to Browser connection string even when calling from the client app, as if at some point the Browser isn't "Unknown" ...
Is there a MUCH easier/simpler way to do this? The way I'm doing it seems really ugly.
I'm quite desperate at the moment as I have no idea why this is happening..
Rather than detecting and switching on the browser type, consider these two suggestions:
Add Custom Request Headers
In your various callers, define a new custom header in your Http request.
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.Headers.Add("CallerType", "ClientApp"); // "Browser", etc.
Then you know exactly and reliably what type of client is calling. This would be hard to get wrong, and couldn't be spoofed/mistaken.
Include The Caller Type in the QueryString
myService.asmx?BrowserType=1
Add a simple new querystring parameter to your .asmx webmethod. This will work just the same in a controlled environment, but if other users/developers get it wrong, or malform the expected values, you'd have to take other measures to correct/handle.
Both allow you to easily determine the connString on the incoming value. Perhaps the absense of a modifier/header, you could assume a default. Your sample question has 2 basic outcomes, and either suggested solution will be easy to extend (browser, client app, iPhone, whathaveyou).

asp.net c# ip address lost after postback?

One of my functions in a class is called GetIpAddress() which returns the following string:
System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"]
This all works well in regular page loads and gets my ip address, but when i for example let a user place a comment, then the ip address is lost after postback and i get an empty string returned.
Am I missing something here maybe?
Kind regards,
Mark
Use these ones:
HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]; // a user is going through a proxy server
HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
HttpContext.Current.Request.UserHostAddress;
Some explanation:
REMOTE_ADDR The IP address of the remote host making the request.
REMOTE_HOST The name of the host making the request. If the server does not have this information, it will set REMOTE_ADDR and leave this empty.
Do you have it wrapped in something like this?
if (!Page.IsPostBack) {
GetIpAddress()
}
You need to either call the function every time, or store it in a Shared variable.
Another option (As #Marc mentioned) would be to simply call Request.UserHostAddress instead of GetIpAddress... it's almost the same amount of typing, but you don't have to have a custom function for it.

How to make sure a POST is requested from specific domain?

Is there any property in HttpRequest that can make sure if the request is a POST request and it is coming from specific domain?
private bool IsRequestedFromDomain(string domain)
{
// Request.Form is from domain ?
return false;
}
Try to use
Request.ServerVariables["HTTP_REFERER"]
Note this header can be faked.
For a list of server variables, please take a look: ASP ServerVariables Collection
HTTP Referer, but it can be modified.
Only way how to be sure is to send some , randomly generated value to form, store it to session, and in IsRequestedFromDomain compare it.
Use:
Request.UrlReferrer, though it isn't reliable as it can be easily faked and may be changed by proxies.

Categories

Resources