Welcome to MSDN Blogs Sign in | Join | Help

Silverlight Web Services Team Blog

For those interested in WCF development on Silverlight, the Silverlight Web Services team just set up a team blog.
Posted by phenning | 0 Comments
Filed under: ,

Custom transport channels and BindingElements

When creating a custom transport channel, you must be sure to remove the encoding binding element from the binding context before returning from your BuildChannelFactory and BuildChannelListener calls. The best place to do this is within the constructor for your transport channel factory or listener.

MessageEncodingBindingElement encodingBindingElement = context.BindingParameters.Remove<MessageEncodingBindingElement>();

Its needs to be removed because there is a validation step that is performed after the channel stack has been fully created. If there are binding elements left in the stack, an InvalidOperaionException will be thrown from Binding.BuildChannelFactory or Binding.BuildChannelListener.

 

Also, be aware if you are building a custom encoder; be sure to add your MessageEncodingBindingElement back to the BindingContext before returning from your BuildChannelListener/BuildChannelFactory methods of your MessageEncodingBindingElement back so that the transport is able to create your encoder. 

context.BindingParameters.Add(this); 
Posted by phenning | 0 Comments
Filed under:

Custom UserNamePassword Validators in .Net Framework 3.5

In the version of WCF that shipped with .Net Framework 3.0 we didn't support custom validators with transport level HTTP security. We received much feedback from the community that this was a highly desired feature, so I'm happy to say we added support for this scenario in the 3.5 release of the .Net Framework.

Note that this is only supported under self hosted services.

Here is what you'll need to do to get it to work:

1. Create your validator:

namespace Sample
{
   using System.ServiceModel;
   using System.IdentityModel.Selectors;
   using System.ServiceModel.Security;

   public class CustomUserNameValidator : UserNamePasswordValidator
   {
       // This method validates users. It allows in two users, test1 and test2 
       // with passwords 1tset and 2tset respectively.
       // This code is for illustration purposes only and 
       // must not be used in a production environment because it is not secure. 
       public override void Validate(string userName, string password)
       {
           if (null == userName || null == password)
           {         
               throw new ArgumentNullException();
           }

           if (!(userName == "test1" && password == "1tset") && !(userName == "test2" && password == "2tset"))
           {
               throw new SecurityTokenException("Unknown Username or Incorrect Password");
           }
      }
   }
}

 2. Configure your service; you'll want to use Transport security and Basic clientCredentialType, this way the authentication header will be protected by SSL.

Configuration for the binding and behavior:

<bindings>
 <wsHttpBinding>
  <binding name="BasicAuthentication">
   <security mode="Transport">
    <transport clientCredentialType="Basic" />
   </security>
  </binding>
 </wsHttpBinding>
</bindings>


<behaviors>
 <serviceBehaviors>
  <behavior name="CustomUserNamePassword">
   <serviceCredentials>
    <userNameAuthentication 
     userNamePasswordValidationMode="Custom" 
     customUserNamePasswordValidatorType="Sample.CustomUserNameValidator, assemblyName"/>
   </serviceCredentials>
  </behavior>
 </serviceBehaviors>
</behaviors>

You can also add the custom validator through code:

host.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = new CustomUserNameValidator();
host.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;

 

Posted by phenning | 3 Comments
Filed under:

Client IP addresses in Orcas

As Nicholas promised, here is some more information about client IP address in Orcas.

In the Orcas release of WCF, we added the ability for services to get the IP address and port of the calling client from your service methods when the underlying transport is Http or Tcp.

You can access the address and port as follows:

namespace Sample
{
    using System;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using System.Net;

    [ServiceContract]
    interface IMyService
    {
        [OperationContract]
        public string ProcessUntyped(Message message);
        [OperationContract]
        public string ProcessTyped(string str);
    }

    class MyService : IMyService
    {
        public string ProcessUntyped(Message message)
        {
            RemoteEndpointMessageProperty endpoint = message.Properties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
            return string.Format("Connected from {0}:{1}", str, endpoint.Address, endpoint.Port);
        }

        public string ProcessTyped(string str)
        {
            OperationContext context = OperationContext.Current;
            MessageProperties properties = context.IncomingMessageProperties;
            RemoteEndpointMessageProperty endpoint = properties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
            return string.Format("You said: '{0}'. Connected from {1}:{2}", str, endpoint.Address, endpoint.Port);
        }
    }
}

Note, if you are using the channel model directly, you can just look at Message.IncomingMessageProperties for the RemoteEndpointMessageProperty

If you are developing your own transport channel, you can attach the property to messages received through your transport channel:

public RemoteEndpointMessageProperty(string address, int port); 

The address specified must be a non zero-length sting and the port should be from 0-65535.

Some additional things to consider:

  1. The IP address and port are as reported from the underlying socket or http.sys and is from the connected machine, so it may be a proxy address.
  2. We don't do any sort of spoof detection, so be careful about using the IP for any sort of security decisions.
  3. For all transports other then http and net.tcp the property will not be on the message.
  4. If you are using composite duplex, the property will be available on the client on replies from the service.
Posted by phenning | 2 Comments
Filed under:

Accessing the Http Query String from a service method.

I'm trying to access the query string used by the client when contacting my service. How can I do this? 

You can access the query string through the HttpRequestMessageProperty.

OperationContext context = OperationContext.Current;
MessageProperties properties = context.IncomingMessageProperties;

HttpRequestMessageProperty requestProperty = properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;

string queryString = requestProperty.QueryString; 
Posted by phenning | 0 Comments
Filed under:

Securing WCF to only respond to local requests.

Is it possible to secure a web service to only respond to local requests over HTTP?

Yes, you just need to make sure that you listen at http://127.0.0.1/MyService/ with HostNameComparisonMode = Exact.

ServiceHost service = new ServiceHost(typeof(MyService), new Uri("http://127.0.0.1/MyService/"));
BasicHttpBinding binding = new BasicHttpBinding();
binding.HostNameComparisonMode = HostNameComparisonMode.Exact;
service.AddServiceEndpoint(typeof(IMyService), binding , "BasicEndpoint");

Also, be sure to run httpcfg or netsh http add urlacl with the 127.0.0.1 address.  

Posted by phenning | 0 Comments
Filed under:

Changing BindingElement settings on a Binding.


We don’t allow you to modify the properties of the binding directly, but you can create a copy of the binding elements used to create a particular binding, alter the desired properties, then use the binding element collection to create a new custom binding. 
BasicHttpBinding basicBinding = new BasicHttpBinding();
BindingElementCollection bindingElementCollection = basicBinding.CreateBindingElements();
bindingElementCollection.Find<HttpTransportBindingElement>().KeepAliveEnabled = false;
CustomBinding myBasicBinding = new CustomBinding(bindingElementCollection);

                    
				            
Posted by phenning | 0 Comments
Filed under:
 
Page view tracker