RE: impersonate in global.asax.cs instead of page load

From: Mike Moore [MS] (michmo@online.microsoft.com)
Date: 11/05/02


From: michmo@online.microsoft.com ("Mike Moore [MS]")
Date: Tue, 05 Nov 2002 04:18:24 GMT


Hi Ed,

QUESTION
Can I move my impersonation code from my pages (it's duplicated in EACH
page), to my global.asax file?

ANSWER
My previous answer was wrong. This code can run in the global.asax file.

The impersonation code is described in:
Q306158 INFO: Implementing Impersonation in an ASP.NET Application
http://support.microsoft.com/support/kb/articles/q306/1/58.asp

Notice that this code calls some functions to perform impersonation and
then calls a function to UNDO the impersonation. It is assumed that your
code which requires impersonation will undo that impersonation before
releasing the thread back to the IIS pool of threads. I thought that
impersonation wouldn't work from the global.asax, and that you couldn't
undo it if you did manage it.

I tried writing the code and found that it did work. Here is my sample code.

Also, I opened three instances of IE on my machine. On one of them, I set
the text box value to "5"; on another "a"; and the final one "b". Then I
set them running. I paused after starting each one so their counters would
be off from each other. The first window correctly showed the system
account. The second one TestUser, and the third, MY_TestUser2. They also
each kept their own session counter variables.

Note that this is a very small test. I'm still concerned about scalability.
So, here's my code.

*** TestImperonate.aspx
I added a text box and a button.
I added the following at the bottom of the page:

  <SCRIPT>
  
  function SubmitMe() {
   Form1.submit();
  }
  
  if (document.Form1.TextBox1.value != "")
   setInterval("SubmitMe()",100);
  </SCRIPT>
  </body>
</HTML>

**** Code-behind

   Private Sub Page_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
      If Session("count") Is Nothing Then
         Session("count") = 1
      Else
         Session("count") += 1
      End If
      Response.Write(Session("count") & "<br>")
      Dim authUserName As String = User.Identity.Name
      Dim aspUserName As String =
System.Security.Principal.WindowsIdentity.GetCurrent.Name
      If authUserName = "" Then
         authUserName = "anonymous"
      End If
      Dim s As String
      s = "You are: " & authUserName & "<br>" & "This page runs as: " &
aspUserName
      Response.Write(s)
   End Sub

**** global.asax

Imports System.Web
Imports System.Web.SessionState
Imports System.Web.Security
Imports System.Security.Principal
Imports System.Runtime.InteropServices

Public Class Global
   Inherits System.Web.HttpApplication

   Dim LOGON32_LOGON_INTERACTIVE As Integer = 2
   Dim LOGON32_PROVIDER_DEFAULT As Integer = 0

   Dim impersonationContext As WindowsImpersonationContext

   Declare Auto Function LogonUser Lib "advapi32.dll" ( _
      ByVal lpszUsername As String, _
      ByVal lpszDomain As String, _
      ByVal lpszPassword As String, _
      ByVal dwLogonType As Integer, _
      ByVal dwLogonProvider As Integer, _
      ByRef phToken As IntPtr) As Integer

   Declare Auto Function DuplicateToken Lib "advapi32.dll" ( _
      ByVal ExistingTokenHandle As IntPtr, _
      ByVal ImpersonationLevel As Integer, _
      ByRef DuplicateTokenHandle As IntPtr) As Integer

   Sub Application_AuthenticateRequest(ByVal sender As Object, ByVal e As
EventArgs)

      If Request.Form("TextBox1") = "a" Then
         impersonateValidUser("TestUser", "michmo1", "abc#123$")
      ElseIf Request.Form("TextBox1") = "b" Then
         impersonateValidUser("MY_TestUser2", "michmo1", "abc#123$")
      End If
   End Sub

   Private Function impersonateValidUser(ByVal userName As String, _
   ByVal domain As String, ByVal password As String) As Boolean
      Dim tempWindowsIdentity As WindowsIdentity
      Dim token As IntPtr
      Dim tokenDuplicate As IntPtr

      If LogonUser(userName, domain, password, LOGON32_LOGON_INTERACTIVE, _
       LOGON32_PROVIDER_DEFAULT, token) <> 0 Then
         If DuplicateToken(token, 2, tokenDuplicate) <> 0 Then
            tempWindowsIdentity = New WindowsIdentity(tokenDuplicate)
            impersonationContext = tempWindowsIdentity.Impersonate()
            If impersonationContext Is Nothing Then
               impersonateValidUser = False
            Else
               impersonateValidUser = True
            End If
         Else
            impersonateValidUser = False
         End If
      Else
         impersonateValidUser = False
      End If
   End Function

   Private Sub Global_ReleaseRequestState(ByVal sender As Object, ByVal e
As System.EventArgs) Handles MyBase.ReleaseRequestState
      If Not (impersonationContext Is Nothing) Then
         Try
            impersonationContext.Undo()
         Catch
         End Try
      End If
   End Sub

**** end of code sample

Do you have any more questions on this?

Thank you, Mike Moore
Microsoft, ASP.NET

This posting is provided "AS IS", with no warranties, and confers no rights.

--------------------
>X-Tomcat-ID: 67719760
>References: <57f8df53.0210302132.6a41c1e6@posting.google.com>
>MIME-Version: 1.0
>Content-Type: text/plain
>Content-Transfer-Encoding: 7bit
>From: michmo@online.microsoft.com ("Mike Moore [MS]")
>Organization: Microsoft
>Date: Sat, 02 Nov 2002 05:54:37 GMT
>Subject: RE: impersonate in global.asax.cs instead of page load
>X-Tomcat-NG: microsoft.public.dotnet.framework.aspnet.security
>Message-ID: <wb2liWjgCHA.2308@cpmsftngxa09>
>Newsgroups: microsoft.public.dotnet.framework.aspnet.security
>Lines: 52
>NNTP-Posting-Host: TOMCATIMPORT2 10.201.218.182
>Path: cpmsftngxa08!cpmsftngxa09
>Xref: cpmsftngxa08 microsoft.public.dotnet.framework.aspnet.security:2863
>
>Hi Ed,
>
>The beginning functions in the global.asax run before impersonation is
>started. This includes BeginRequest.
>
>It might work to put impersonation in an httpModule. I'll look into this
>and post what I find on Monday.
>
>Thank you, Mike Moore
>Microsoft, ASP.NET
>
>This posting is provided "AS IS", with no warranties, and confers no
rights.
>
>--------------------
>>From: EDLENO@safeco.com (Ed leNoir)
>>Newsgroups: microsoft.public.dotnet.framework.aspnet.security
>>Subject: impersonate in global.asax.cs instead of page load
>>Date: 30 Oct 2002 21:32:48 -0800
>>Organization: http://groups.google.com/
>>Lines: 16
>>Message-ID: <57f8df53.0210302132.6a41c1e6@posting.google.com>
>>NNTP-Posting-Host: 165.121.32.32
>>Content-Type: text/plain; charset=ISO-8859-1
>>Content-Transfer-Encoding: 8bit
>>X-Trace: posting.google.com 1036042369 27662 127.0.0.1 (31 Oct 2002
>05:32:49 GMT)
>>X-Complaints-To: groups-abuse@google.com
>>NNTP-Posting-Date: 31 Oct 2002 05:32:49 GMT
>>Path:
>cpmsftngxa09!cpmsftngxa08!tkmsftngp01!newsfeed00.sul.t-online.de!t-online.d
e
>!news-lei1.dfn.de!newsfeed.freenet.de!newsfeed.news2me.com!sn-xit-05!sn-xit
-
>01!sn-xit-04!supernews.com!postnews1.google.com!not-for-mail
>>Xref: cpmsftngxa09 microsoft.public.dotnet.framework.aspnet.security:2797
>>X-Tomcat-NG: microsoft.public.dotnet.framework.aspnet.security
>>
>>I thought I could do an Impersonate in a global event but it doesn't
>>seem to work. By the time the page loads the current identity is back
>>to the default value. I can do the impersonate in the page load event
>>and everything works.
>>
>>The Microsoft samples also use page load, but I thought doing the
>>impersonate in BeginRequest would do the trick.
>>
>>At what point is the thread created for a page/request? I'd like to
>>centralize the code in the global.asax.cs. Page load can work too, but
>>it just seems it should work as an application event.
>>
>>(I've also tried the SetThreadIdentity in ApplicationStart (and
>>BeginRequest) but neither of those worked. )
>>
>>- Ed
>>
>
>


Quantcast