Step 1: Create the MessageInspector and EndpointBehavior:
public class RequestSourceEndpointBehavior : IEndpointBehavior, IDispatchMessageInspector
{
private static readonly Logger.ILog log = Logger.CreateLog();
public String AllowedHosts { get; set; }
public void Validate(ServiceEndpoint endpoint)
{
}
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(this);
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
RemoteEndpointMessageProperty remoteEndpoint = request.Properties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
IPAddress address = IPAddress.Parse(remoteEndpoint.Address);
var dnsEntry = Dns.GetHostEntry(address);
var hostname = dnsEntry.HostName.ToString();
Console.WriteLine(address.ToString());
Console.WriteLine(hostname);
log.Info(String.Format("Request comes from {0}", hostname));
if (!IsRequestSourceAllowed(hostname))
{
log.Error(String.Format("Request comes from {0} is denied", hostname));
throw new WebFaultException<String>(String.Format("Failed : Request Source {0} is not allowed", hostname),
HttpStatusCode.Forbidden);
}
return instanceContext;
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
}
private bool IsRequestSourceAllowed(String hostname)
{
return AllowedHosts.Split(',').Any(hostname.Contains);
}
}
Step 2: Create Endpoint Extension:
public class RequestSourceEndpointBehaviorExtension : BehaviorExtensionElement
{
[ConfigurationProperty("allowedHosts")]
public String AllowedHostnames
{
get { return this["allowedHosts"] as string; }
set { this["allowedHosts"] = value; }
}
private static readonly Logger.ILog log = Logger.CreateLog();
protected override object CreateBehavior()
{
log.Info("RequestSourceEndpointBehavior is init with config allowed hosts: " + AllowedHostnames);
var behavior = new RequestSourceEndpointBehavior();
behavior.AllowedHosts = this.AllowedHostnames;
return behavior;
}
public override Type BehaviorType
{
get { return typeof(RequestSourceEndpointBehavior); }
}
}
Step 3: Apply Message Inspector in Config:
Adding the extension first under system.serviceModel/extensions/behaviorextensions
then, in the endpoint behavior binding include the custom message inspector.
Note:
WebFaultException from .NET 4.0 is used to allow the custom error message.