Temporary Identity Impersonation in ASP.NET

Posted by Ryan Baxter Tue, 27 May 2008 16:01:00 GMT

Uploading files in an ASP.NET application is relatively easy to do. Uploading to a remote machine is a little bit trickier, but certainly doable. I followed a set of instructions on aspalliance.com, but rather than declare an account to impersonate in my web.config file, I decided to do it in code. That way I could use impersonation only when needed and encapsulate it for later use.

I referred to an article on Microsoft’s Help and Support website about how to implement impersonation. Their code worked great, but I decided to put it in a class to help keep things DRY.

using System;
using System.Web;
using System.Web.Security;
using System.Security.Principal;
using System.Runtime.InteropServices;

namespace Utilities
{    
    public class ImpersonateUser
    {
        public const int LOGON32_LOGON_INTERACTIVE = 2;
        public const int LOGON32_PROVIDER_DEFAULT = 0;

        WindowsImpersonationContext impersonationContext;

        [DllImport("advapi32.dll")]
        public static extern int LogonUserA(String lpszUserName,
            String lpszDomain,
            String lpszPassword,
            int dwLogonType,
            int dwLogonProvider,
            ref IntPtr phToken);
        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern int DuplicateToken(IntPtr hToken,
            int impersonationLevel,
            ref IntPtr hNewToken);

        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool RevertToSelf();

        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public static extern bool CloseHandle(IntPtr handle);

        public bool ImpersonateValidUser(String userName, String domain, String password)
        {
            WindowsIdentity tempWindowsIdentity;
            IntPtr token = IntPtr.Zero;
            IntPtr tokenDuplicate = IntPtr.Zero;

            if (RevertToSelf())
            {
                if (LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE,
                    LOGON32_PROVIDER_DEFAULT, ref token) != 0)
                {
                    if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
                    {
                        tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
                        impersonationContext = tempWindowsIdentity.Impersonate();
                        if (impersonationContext != null)
                        {
                            CloseHandle(token);
                            CloseHandle(tokenDuplicate);
                            return true;
                        }
                    }
                }
            }
            if (token != IntPtr.Zero)
                CloseHandle(token);
            if (tokenDuplicate != IntPtr.Zero)
                CloseHandle(tokenDuplicate);
            return false;
        }

        public void UndoImpersonation()
        {
            impersonationContext.Undo();
        }
    }
}

After referencing my Utilities namespace I was then able to impersonate the account required for uploading:

if (FileUpload1.HasFile)
{
    ImpersonateUser impersonateUser = new ImpersonateUser();

    if (impersonateUser.ImpersonateValidUser("userName", "", "password"))
    {
        FileUpload1.SaveAs(Server.MapPath("~/files/fileName.txt"));
        impersonateUser.UndoImpersonation();
    }
    else
    {
        throw new Exception("Identity impersonation has failed.");
    }   
}

*The SaveAs method of the FileUpload control requires a root path. Using Server.MapPath will provide the root path of your IIS virtual folder.

Rockscroll Visual Studio Add-in

Posted by Ryan Baxter Tue, 13 May 2008 13:32:00 GMT

Last Friday, Scott Hanselman announced the release of the Rockscroll Visual Studio Add-in. Rockscroll replaces Visual Studio’s code-view scrollbar with a miniature visual representation of your source code. This feature makes navigation in large source files that much easier.

Before Rockscroll, I’d oftentimes make mental notes of the scrollbar’s position while traversing code. That, and when spending a lot of time on a project I’d become so familiar with the source code that I’d begin to recognize most code blocks by shape. Rockscroll provides both of these mnemonic devices, but with less brain work. That is a good thing. Thank you, Rocky Downs. Can I have this in NetBeans? :)

A Few Date Methods

Posted by Ryan Baxter Tue, 06 May 2008 18:45:00 GMT

An ASP.NET project of mine recently required the calculation of the start and end date of the current date’s previous month. This was more difficult putting into words than code. It did, however, get me thinking about other common date routines.

public static DateTime FirstDayOfPreviousMonth
{
    get
    {
        return new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1).AddMonths(-1);
    }    
}

public static DateTime LastDayOfPreviousMonth
{
    get
    {
        return new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1).AddDays(-1);
    }
}

Being preemptive, I decided to include a few methods for determining the start and end date of the current date’s fiscal quarter. I started by calculating the current date’s quarter. This was accomplished with just a little division.

public static int CurrentQuarter
{
    get
    {
        return (DateTime.Now.Month + 2) / 3;
    }
}

Finding the start and end dates of the current quarter was harder, but could still be expressed in a single line of code (or two).

public static DateTime FirstDayOfCurrentQuarter
{
    get
    {
        return new DateTime(DateTime.Now.Year, 1 + ((CurrentQuarter - 1) * 3), 1);
    }
}

public static DateTime LastDayOfCurrentQuarter
{
    get
    {
        int lastMonthOfCurrentQuarter = 3 + ((CurrentQuarter - 1) * 3);

        return new DateTime(DateTime.Now.Year, lastMonthOfCurrentQuarter, DateTime.DaysInMonth(DateTime.Now.Year, lastMonthOfCurrentQuarter));
    }
}

I’d like to extend this collection to include other common date routines. Feel free to post your date methods as comments if you’d like to share.

*The methods I’ve created for calculating the current quarter’s start and end dates assume the fiscal year starts on January 1st. This may not be suitable for your needs.

System.Drawing.Color Hex Values

Posted by Ryan Baxter Wed, 16 Apr 2008 23:29:00 GMT

Do you know the hexidecimal value of PapayaWhip? How about BlanchedAlmond? Me either. I’m not a big fan of the System.Drawing.Color structure in the Microsoft .NET Framework. I don’t think the addition of color names makes good framework design sense. Unless you’re an Interior Designer; the majority of these colors won’t make sense to you either.

I’ve recently spent time reworking a few design elements of an ASP.NET website. All design related ASP.NET attributes were replaced with Cascading Style Sheets (CSS) where applicable. Unfortunately the website was spattered with named colors from the System.Drawing.Color structure. To help replace these named colors with hexadecimal values, I found the following resource extremely helpful.

http://www.opinionatedgeek.com/DotNet/Tools/Colors/default.aspx

Expect the Unexpected: Source Fource

Posted by Ryan Baxter Wed, 20 Feb 2008 16:09:00 GMT

OK, this is ridiculous. I must be getting too old for their marketing demographic. I do, however, look remarkably similar to figure below when wearing my dobak.

Automated Build Flurry

Posted by Ryan Baxter Tue, 12 Feb 2008 22:39:00 GMT

Quite a few automated build articles have been cropping up this week over at CodeBetter.Com. The first, How do you build your application?, by Kyle Baley, asks Developers of the .NET community how they manage builds using the NAnt toolkit. Jeffrey Palermo responded with a helpful post including a link to his own NAnt build template. Kyle then followed-up with a few humorous links to graphics of common build scenarios.

CodeBetter.Com has provided me with an overwhelming amount of great .NET content over the years and the above articles couldn’t have arrived at a better time. My spare cycles at Primus Technologies Corporation have been few and far between, but those found have been spent configuring the companies Continous Integration system. I must admit that I was pleased that my own NAnt build script looked remarkably similar to Jeffrey Palermo’s template. :)

Of all of the work involved in developing software, build automation and Continuous Integration are my favorite. When Continuous Integration is implemented correctly it should function like an assembly line. Just like Ford Motor Company, your software will see improvements in efficiency and development time. If you’re a .NET Developer and confused by what I’ve written thus far then you should definitely familiarize yourself with these concepts. At the very least, I’d recommend researching the following tools:

In addition, Scott Hanselman has a few podcasts that could also be helpful. Listen carefully, read diligently, and improve your software. Be better at your craft.