318
A web page can take action based on a username, using the following code: If Me.User.Identity.Name = SOME-DOMAIN\daveg Then
Do something. Else
Do something else. End If
Role membership is tested by using the IsInRole method of the IPrincipal type. For example: If Me.User.IsInRoleSOME-DOMAIN\Employees Then
Do something. Else
Do something else. End If
6.10.3 Accessing Network Resources
After a user authenticates to the web application, it may be appropriate for the web application to access network resources on behalf of the user. For example, a web application might give a
companys employees access to their corporate email accounts while away from the office. To do this, the web application must log into the companys email server and retrieve information belonging to the
person using the application. Normally, such access to private information is blocked by the Windows security mechanism because the web-server process does not have appropriate rights to access
resources owned by the user. There are two ways to resolve this issue. One is to give the necessary rights to the process under which the web server is running; the other is for the web server to
impersonate the authenticated user. Each is discussed here in turn.
6.10.3.1 IUSR_ComputerName
When IIS is installed on a computer, the installation process creates a username on that computer called IUSR_
ComputerName , where
ComputerName is the name of the computer on which IIS is
installed. This is the default username under which web requests are run. IIS can be configured to use any user account for this purpose, including domain user accounts. If youre writing a web application
that accesses network resources but doesnt depend on the identity of the web user for rights to those resources, set up a domain username that has rights to the resources and configure IIS to use that
username. See the IIS documentation for information on how to configure this username.
6.10.3.2 Impersonation
Applications that need to access resources using the rights of the currently authenticated web user must use impersonation. Impersonation is a Windows security term that refers to a threads ability to
assume a different security identity for a period of time. In ASP.NET, it allows an application to assume the identity of the web user so that the application can access resources on behalf of the user.
Impersonation happens automatically when using Windows authentication as described earlier in this chapter. The application is written simply to access the desired resources, and the Windows security
mechanism ensures that the access succeeds or fails depending on the end users access rights.
If the application is using Forms authentication, impersonation must be explicitly coded. Unfortunately, the .NET Framework doesnt provide a mechanism to do this. If an application that uses Forms
authentication needs to impersonate a user, it must call directly into the Windows API. The general steps are:
1. Call the Windows LogonUser function to authenticate a given user. 2. Instantiate a WindowsIdentity object defined in the System.Security.Principal namespace to
represent the authenticated user. 3. Call the WindowsIdentity objects Impersonate method to impersonate the user.
319
4. Access the protected resource. 5. Undo the impersonation.
Ex am ple 6- 16 gives the complete code for this process.
Example 6-16. Impersonating a Windows user from code
Values used by the LogonUser functions logonType parameter Public Enum LogonType
LOGON32_LOGON_INTERACTIVE = 2 LOGON32_LOGON_NETWORK = 3
LOGON32_LOGON_BATCH = 4 LOGON32_LOGON_SERVICE = 5
LOGON32_LOGON_UNLOCK = 7 LOGON32_LOGON_NETWORK_CLEARTEXT = 8
LOGON32_LOGON_NEW_CREDENTIALS = 9 End Enum
Values used by the LogonUser functions logonProvider parameter Public Enum LogonProvider
LOGON32_PROVIDER_DEFAULT = 0 LOGON32_PROVIDER_WINNT35 = 1
LOGON32_PROVIDER_WINNT40 = 2 LOGON32_PROVIDER_WINNT50 = 3
End Enum Declare Function LogonUser Lib advapi32.dll Alias LogonUserA _
ByVal username As String, _ ByVal domain As String, _
ByVal password As String, _ ByVal logonType As LogonType, _
ByVal logonProvider As LogonProvider, _ ByRef token As IntPtr _
As Integer Private Sub DoSomethingUseful
Logon credentials Dim username As String = username
Dim domain As String = DOMAIN Dim password As String = password
A handle to the user who will be impersonated Dim token As IntPtr
Log the user into Windows. Dim bLogonSuccessful As Boolean = Convert.ToBoolean _
LogonUser _ username, domain, password, _
LogonType.LOGON32_LOGON_NETWORK, _ LogonProvider.LOGON32_PROVIDER_DEFAULT, token
If Not bLogonSuccessful Then Throw an exception.
End If Create a WindowsIdentity object that represents the logged-in user.
Dim ident As New System.Security.Principal.WindowsIdentitytoken Impersonate the user.
Dim ctx As System.Security.Principal.WindowsImpersonationContext = _ ident.Impersonate
320
Access the protected resource here. ...
Stop impersonating the user. ctx.Undo
End Sub
The LogonUser function is not part of the .NET Framework—it is part of the underlying Windows API. To access it, one must use the
Declare statement or use the .NET Frameworks PInvoke capability.
In Ex am ple 6- 16
, the Declare
statement is used to give the code access to the LogonUser function. The LogonUser function takes six parameters. The first three,
username ,
domain , and
password ,
provide the logon credentials of the user who will be authenticated. The next two parameters, logonType
and logonProvider
, provide further control of the logon process. A discussion of these two parameters is beyond the scope of this book. Search for LogonUser in the Microsoft Developer
Network MSDN online documentation ht t p: m sdn.m icr osoft .com libr ar y
for details about the values that can be provided. The final parameter,
token , is a
ByRef parameter that receives a handle
to the logged-in user if the function is successful. The return value is an Integer that indicates whether the function was successful. A return value of
indicates failure; anything other than indicates success. In
Ex am ple 6- 16 , this value is converted to a Boolean using the Convert class
defined in the System namespace. After the user is logged in, the
token value is passed to the constructor of the WindowsIdentity class
defined in the System.Security.Principal namespace. This creates a WindowsIdentity object that represents the authenticated user. This object has an Impersonate method, which is called to start the
impersonation. An object of type WindowsImpersonationContext defined in the System.Security.Principal namespace is returned from the Impersonate method. This object is used
later to undo the impersonation. After the Impersonate method is called, the code can safely access protected resources. When finished, the Undo method of the WindowsImpersonationContext object is
called to stop impersonation.
6.11 Designing Custom Controls
ASP.NET provides the ability to define two kinds of custom controls: user controls and server controls. The purpose of both is the same: to encapsulate visual and programmatic behaviors for use on web
pages. For example, a control can be used to encapsulate a navigation bar that appears on every page in a site. Their differences lie in how they are created and in their capabilities. User controls are
created in much the same way as standard ASP.NET pages and can include HTML, embedded code, and code-behind files. This allows web developers to quickly and easily create controls using
techniques with which they are already familiar. In contrast, server controls are created entirely in code and provide much more sophisticated control over rendering, postback processing, and event
generation. This means that custom server controls can do everything that built-in ASP.NET server controls can do. Even so, user controls are usually the right choice because they are so simply
created. Server controls are not needed unless user controls are not sufficient for a given purpose. This section shows how to create both kinds of controls.
6.11.1 User Controls
The easiest way to create a new control is to aggregate and modify the functionality of one or more existing controls. This is done by creating a user-control file .ascx and then referencing it from a web
page file .aspx. Ex am ple 6- 17
shows a simple user-control file.
Example 6-17. A user control for implementing a menu