2009 m. gruodžio 27 d., sekmadienis

Communication between WCF and JBoss server via REST

Part 2: Using ssl + basic auth

Providing plain credentials over a secure transport layer is considered as quite secure way to communicate.

Let's build a secure Rest client:

using (HttpClient client = new HttpClient()) // needs disposal
{
  client.DefaultHeaders.ContentType = "text/xml";
  client.TransportSettings.Credentials = new NetworkCredential("username", "password");
 
  ServicePointManager.Expect100Continue = false;

 ServicePointManager.ServerCertificateValidationCallback = (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) => { return true; };

 Account newAccount = new Account()
  {
     Id = 0,
     Name = “FirstUser”
  };

  HttpContentExtensions.CreateXmlSerializable<Account>(newAccount);
  HttpResponseMessage resp = lient.Post("http://example/account", newAccount);

  resp.EnsureStatusIsSuccessful(); // fires exceptions
  
  Status status = resp.Content.ReadAsXmlSerializable<Status>();
}

The property ServicePointManager.Expect100Continue solves different Http1.1 interpretation problem between Java .NET.

This case is covered in the HTTP/1.1 (RFC 2616) specification in section 8.2.3:

"Because of the presence of older implementations, the protocol allows ambiguous situations in which a client may send "Expect: 100-continue" without receiving either a 417 (Expectation Failed) status
or a 100 (Continue) status. Therefore, when a client sends this header field to an origin server (possibly via a proxy) from which it has never seen a 100 (Continue) status, the client SHOULD NOT wait for an indefinite period before sending the request body."

This problem appeared only when I'd added security to my client. Probably it is related to increasing waiting time.

ServicePointManager.ServerCertificateValidationCallback is used only in testing mode. The purpose is to override certificate validation which would cause exception becouse we don't have one in a testing stage.



References:
  • http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html 

2009 m. lapkričio 29 d., sekmadienis

Communication between WCF and JBoss server via REST

Communication between WCF and JBoss server via REST

Targets:

  • Build a client to communicate with JBoss(Java application server) RESTEasy REST service
  • Use ssl combined basic auth to ensure security
  • Use direct xml - object serialization
  • Explore WCF REST Starter Kit possibilities

Issues:
  • Http 1.1 different standards interpretation by .NET and java
  • Adding custom xml namespace prefixes to request message

PART 1 - Simple client

Two different ways for calling REST from .NET :
  • Using simple HttpWebRequest and HttpWebResponse objects. (old way, more technical details)
  • Using WCF REST Starter Kit.

Let’s focus on the second type. It saves some lines of code and hides unnecessary technical details.
We have a task to create a user on the remote system and receive the status.

So far we’ve successfully created the following DTO objects (by using xsd tool that comes with Visual Studio or by hand:
  • Simplified user with id and Name fields
  • Status with success/failure indicator + optional message (failure case)
///
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlRootAttribute(IsNullable = false, ElementName = "account")]
public class Account
{

private long idField;
private string name;

///
[System.Xml.Serialization.XmlElementAttribute(ElementName="id")]
public long Id
{
   get
   {

      return this.idField;
   }
  set
  {
     this.idField = value;
   }

}
[System.Xml.Serialization.XmlElementAttribute(ElementName = "name")]
public string Name
{
   get
   {
     return this.name;
   }
   set
   {
     this.name = value;
   }
}
}

[System.SerializableAttribute()]
[System.Xml.Serialization.XmlRootAttribute(IsNullable = false, ElementName = "status")]
public class Status
{

private string msg;
private bool successField;

///
[System.Xml.Serialization.XmlElementAttribute(ElementName = "msg")]
public string Msg
{
   get
   {
     return this.msg;
   }
   set
   {
     this.msg = value;
   }
}
[System.Xml.Serialization.XmlElementAttribute(ElementName = "success")]
public bool Success
{
   get
   {
     return this.successField;
  }
   set
   {
     this.successField = value;
   }

}
}


Then our code looks like:



using (HttpClient client = new HttpClient()) // needs disposal
{
  client.DefaultHeaders.ContentType = "text/xml";
  Account newAccount = new Account()
  {
     Id = 0,
     Name = “FirstUser”
  };

  HttpContentExtensions.CreateXmlSerializable<Account >(newAccount);
  HttpResponseMessage resp = lient.Post("http://example/account", newAccount);

  resp.EnsureStatusIsSuccessful(); // fires exceptions
  
  Status status = resp.Content.ReadAsXmlSerializable<Status>();
}

HttpContentExtensions class provides helper methods for Http content creation.

Next part will provide security for our client