rulururu

post K2 blackpearl Client Impersonation - Suggested Design Pattern

June 26th, 2008

Filed under: How To, K2, Technical, blackpearl — Colin

The K2 blackpearl client API has impersonation functionality that I make heavy use of in my current project. A sample might look like this:

View CodeCSHARP
    //Open a client connection (using a helper function) 
    Connection conn = OpenK2ClientConnection(); 
 
    //Impersonate the desired user 
    conn.ImpersonateUser(userName); 
 
    //Do whatever work you need to do as the impersonated user 
 
    //Revert back to the original user 
    conn.RevertUser();

This works quite well, but you have to always be sure to call conn.RevertUser() at the end of your impersonation call so that you revert back to the original user (assuming you plan on reusing the same connection). If you don’t, you’ll continue to use the impersonated user context which will obviously lead to unintended consequences. To be safer, a try/finally makes for a better approach.

View CodeCSHARP
    //Open a client connection (using a helper function) 
    Connection conn = OpenK2ClientConnection(); 
    try 
    { 
        //Impersonate the desired user 
        conn.ImpersonateUser(userName); 
 
        //Do whatever work you need to do as the impersonated user 
    } 
    finally 
    { 
        //Revert back to the original user 
        conn.RevertUser(); 
    }

The above code should always correctly revert our user, but it’s kind of a pain to write, results in a lot of “plumbing”/duplicate code and increases the chances implementing it will be overlooked somwhere. To overcome this, I recommend something like the following pattern be used:

View CodeCSHARP
    Connection conn = OpenK2ClientConnection(); 
    //Impersonate 
    using( Impersonation.Impersonate(userName, conn ) 
    { 
        //Do whatever work you need to do as the impersonated user 
    }

The result is a significant reduction in lines coded and guaranteed user revertion. This is accomplished by creating a custom class (Impersonation) which implements IDisposable and which always calls RevertUser at disposal. I use this approach in my BWT framework and it works flawlessly.

Here is my implementation of the Impersonation class:

View CodeCSHARP
    public class Impersonation : IDisposable 
    { 
        private Connection _conn = null; 
 
        private Impersonation(Connection conn) 
        { 
            _conn = conn; 
        } 
 
        #region Impersonate Methods 
 
        public static Impersonation Impersonate(string userName, Connection conn) 
        { 
            conn.ImpersonateUser(userName); 
 
            return new Impersonation(conn); 
        } 
 
        #endregion Impersonate Methods 
 
        #region IDisposable Members 
 
        public void Dispose() 
        { 
            _conn.RevertUser(); 
        } 
 
        #endregion 
    }

No Comments »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a comment

ruldrurd
Powered by WordPress, Web Design by Laurentiu Piron
Entries (RSS) and Comments (RSS)