Zulfiqar's weblog

Architecture, security & random .Net

Archive for December, 2008

Geneva Framework & S4U

Posted by zamd on December 23, 2008

Current bits of Geneva framework shipped with a service known as Microsoft "Geneva" Claims To NT Token Service. This service can be used to get a Kerberos token for a user without requiring its password. Windows Server 2003 added a little known extension to Kerberos known as Service-4-User (S4U) and this service internally uses this feature to get a Kerberos token.

 

S4U tokens usually have some special restriction to avoid their misuse. So if service is not running under LocalSystem account then the returned token will only have  impersonation level of Identify, so you can query the returned token for group information etc but you cannot impersonate it to open kernel objects etc.  However if the caller is running as LocalSystem then LSA returns a token with the impersonation level of Impersonate and you can indeed impersonate the user and access kernel object on his behalf.  “Claims To NT Token Service” runs under LocalSystem – so a token acquired using this service can be used to impersonate as well.

This service is actually exposed using a WCF endpoint and as part of Geneva framework you get a proxy client for this service as well. Here is an example of using this proxy client to get a token.

 

    class Program

    {

        static void Main(string[] args)

        {

            string filePath = @"C:\temp\data.txt";

            string data;

            var wi = S4UClient.UpnLogon("abu@bccoss.com");

            using (var wic = wi.Impersonate())

            {

                data = File.ReadAllText(filePath);

            }

        }

    }

 

Posted in Geneva | Leave a Comment »

Enabling InstanceProvider for Singleton Services

Posted by zamd on December 18, 2008

Many people like to use Dependency Injection containers (Unity, Windsor etc) to create WCF service objects and the common approach is to use WCF’s InstanceProvider extensibility hook to delegate instance creation to a DI container. By default this approach however doesn’t work for singleton services as InstanceProvider is never called. There is very simple fix to this problem which I’m going to explain in this post but first little background information.

WCF instancing revolve around following 3 objects:

 

InstanceContextProvider is very early in dispatch pipeline and has access to channel and message. This provider has the flexibility to reuse instance contexts based on either sessions or any other unique id in messages. When InstanceContextProvider returns an existing InstanceContext, dispatcher sees whether the returned InstanceContext has an active instance, if yes then that active instance gets used and InstanceProvider is never invoked. If there is no active instance then InstanceProvider is invoked to get one.

So when you configure your service’s InstanceContextMode=Single, there will always be cached instance and your provided will never be called. A simple fix is to overwrite the InstanceContext with a brand new one thus destroying the cached object.

    dispatchRuntime.SingletonInstanceContext = new InstanceContext(serviceHostBase);

This above change will result in your InstanceProvider to be called (only first time) to get the required service instance. Here is complete code.

 

    [ServiceContract]

    public interface ICalc

    {

        [OperationContract]

        int Add(int a, int b);

    }

    [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]

    public class Calc : ICalc

    {

        public int Add(int a, int b)

        {

            Console.WriteLine(this.GetHashCode());

            return a + b;

        }

    }

 

    class Program

    {

        static void Main(string[] args)

        {

            ServiceHost h = new ServiceHost(typeof(Calc));

            h.Description.Behaviors.Add(new MyBv());

            h.Open();

            var cf = new ChannelFactory<ICalc>("*");

            cf.Open();

            var proxy = cf.CreateChannel();

            for (int i = 0; i < 10; i++)

            {

                proxy.Add(11, 2);

            }

            Console.ReadLine();

        }

    }

 

 

    public class MyBv : IServiceBehavior

    {

        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)

        {

            var cd = serviceHostBase.ChannelDispatchers[0] as ChannelDispatcher;

            var dispatchRuntime = cd.Endpoints[0].DispatchRuntime;

            dispatchRuntime.SingletonInstanceContext = new InstanceContext(serviceHostBase);

            dispatchRuntime.InstanceProvider = new MyInstanceProvider();

        }

    }

    public class MyInstanceProvider : IInstanceProvider

    {

 

        public object GetInstance(InstanceContext instanceContext, System.ServiceModel.Channels.Message message)

        {

            var c =  new Calc();

            return c;

        }

 

    }

Posted in WCF | Leave a Comment »

JSON vs XML encoder performance

Posted by zamd on December 16, 2008

Tim has summarized that both JSON and XML has their unique place. JSON encoded data has smaller wire footprint and is easier to convert back into Javascript objects using javascript:eval function so it’s generally favoured in AJAX scenarios. I was asked about WCF encoding performance for JSON and XML (text). My initial guess was there shouldn’t be much difference in encoding performance so to validate my assumption I wrote following code to test the encoding performance and indeed it’s roughly the same.

 

To encode same message 300000 times it  took following number of ticks (roughly equal).

 

XML encoding ticks = 63810463

JSON encoding ticks = 68490315

I used following code in my testing.

 

namespace encodingPerformance

{

    [DataContract]

    public class Data

    {

        [DataMember]

        public string Name { get; set; }

        [DataMember]

        public string Address { get; set; }

        [DataMember]

        public double Salary { get; set; }

        [DataMember]

        public string Email { get; set; }

        [DataMember]

        public string SpouseName { get; set; }

        [DataMember]

        public int FamilyCount { get; set; }

        [DataMember]

        public int Age { get; set; }

    }

    class Program

    {

        static void Main(string[] args)

        {

            var d = new Data

            {

                Address = "15 ********* aveneu.",

                Age = 29,

                Email = "uzhadaf@ gamicl.com",

                FamilyCount = 3,

                Name = "******* rAhmeD2",

                Salary = 111212121.121,

                SpouseName = "Sigrasdf"

 

            };

 

            const int ITER = 3000000;

 

            var ms = new MemoryStream();

            var tbe = new TextMessageEncodingBindingElement();

            tbe.MessageVersion = MessageVersion.None;

 

            var msg = Message.CreateMessage(MessageVersion.None, "", d);

            var buf = msg.CreateBufferedCopy(int.MaxValue);

 

            var sw = Stopwatch.StartNew();

            for (int i = 0; i < ITER; i++)

            {

                msg = buf.CreateMessage();

                tbe.CreateMessageEncoderFactory().Encoder.WriteMessage(msg, ms);

                ms.Seek(0, SeekOrigin.Begin);

            }

 

            sw.Stop();

            Console.WriteLine("XML encoding ticks = {0} ", sw.ElapsedTicks);

 

            msg = Message.CreateMessage(MessageVersion.None, "", d, new DataContractJsonSerializer(typeof(Data)));

            buf = msg.CreateBufferedCopy(int.MaxValue);

            var wbe = new WebMessageEncodingBindingElement();

            var prop = new WebBodyFormatMessageProperty(WebContentFormat.Json);

 

            // measure JSON encoding time….

            sw = Stopwatch.StartNew();

            for (int i = 0; i < ITER; i++)

            {

                msg = buf.CreateMessage();

                msg.Properties.Add(WebBodyFormatMessageProperty.Name, prop); //JSON encode

                wbe.CreateMessageEncoderFactory().Encoder.WriteMessage(msg, ms);

                ms.Seek(0, SeekOrigin.Begin);

            }

            sw.Stop();

            Console.WriteLine("JON encoding ticks = {0} ", sw.ElapsedTicks);

 

        }

    }

}

Posted in WCF | Leave a Comment »