Click here to Skip to main content
15,881,852 members
Articles / Web Development / CSS

A Windows Logon, Web User Control Implementation - in ASP.NET

Rate me:
Please Sign up or sign in to vote.
4.27/5 (17 votes)
24 Nov 20035 min read 233K   3.3K   88   24
A classic example of implementing reusable web user control, with supporting controls and classes to keep the code manageable

Sample Image - ASPdotnet_LoginControl.gif

Overview

This article attempts to work out an example of the impersonation namespace in .NET, to logon a user through a webpage, with his Windows logon credentials. The traditional way of logging in users using their Windows authentication is by enabling the Basic Authentication property of the web application in IIS.

But, using the control, we can eliminate the necessity of controlling logon through IIS, and enable it through our code. This opens up a considerable area of control through code. We can hence have a control on which user login is requested, and on which domain and all that.

We will discuss the creation of the project and the logic I had in mind while developing it. The completed and tested code, that was developed using VS.NET is attached to this article.

Introduction

We create two web user controls.

  • WindowsLoginControl

    This has the implementation and UI for the login pane. It has two UIs, one for new users, one for already logged in users. A session variable maintains the state of the login to determine which UI to show. Code in this control calls the logInUser class' shared method to process the login.

  • ErrorControl

    This has implementation and UI for an error reporting pane. When errors occur, other controls on the page update a session variable, which is checked when this control loads. When there's no error, we display an 'Under construction' message (This may be removed in release versions).

NOTE: We could have implemented the logic of this control also into the WindowsLoginControl, but having this as a separate control allows us to easily move the control on the UI of a target page in VS.NET.

  • A LoginUser class with a shared method for processing the login

    This has implementation of the login process. A shared method takes username, password and domain as parameters and tries a Windows logon with the data, and we impersonate the user.

  • A logoff page which clears user's session and abandons it

    This is to cleanup the sessions, and make the totalActiveUser count on the system more reliable.

The Code

Open an ASP.NET project. Select the project in the Solution Explorer and create a new 'web user control' item. Develop the UI for it... probably two text boxes... for username and password and a 'Login' button.

We make another UI, which shows a viewpane with the details of user login.

We show the login form when the user hasn't logged into the system, and show a login details view after the user logs in. Users login with their Windows authentication (this means that we should have created users on the server and the domain for this to work).

The windowsLoginControl calls shared function LogInThisUser() of the LogInUser class which logs-in the user and impersonates the logged-on user. The code that does this is as below:

VB
Dim loggedOn As Boolean = LogonUser(username, _ 
        domainname, password, 3, 0, token1)
'impersonate user
Dim token2 As IntPtr = New IntPtr(token1)
Dim mWIC As WindowsImpersonationContext = _
    New WindowsIdentity(token2).Impersonate

For this, we declare the loginuser class with the proper namespaces, and in a manner to include unmanaged code. We need unmanaged code to be written, because I believe we don't have a managed code implementation of the LogonUser function of Windows to do the same.

VB
'include permissions namespace for security attributes
'include principal namespace for windowsidentity class
'include interopservices namespace for dllImports.

Imports System.Security.Principal
Imports System.Security.Permissions
Imports System.Runtime.InteropServices

<Assembly: SecurityPermissionAttribute
  (SecurityAction.RequestMinimum, UnmanagedCode:=True)> 
Public Class LogInUser

    <DllImport("C:\\WINDOWS\\System32\\advapi32.dll")> _
    Private Shared Function LogonUser(ByVal _ 
        lpszUsername As String, ByVal lpszDomain _
        As String, ByVal lpszPassword As String, _
        ByVal dwLogonType As Integer, _ 
        ByVal dwLogonProvider As Integer, _
        ByRef phToken As Integer) As Boolean
    End Function

    <DllImport("C:\\WINDOWS\\System32\\Kernel32.dll")> _
    Private Shared Function GetLastError() As Integer
    End Function

We can also find whether the logonuser function generated errors, by calling the GetLastError method.

We use session variables to keep track of the user's login information and last access. We use an application variable to keep track of the total active users in the system.

Below code is part of this implementation (can be found in windowsLoginControl.ascx.vb):

VB
Session.Add("LoggedON", True)
Session.Add("Username", sRetText)

Application.Item("TotalActiveUsers") += 1

lblUserName.Text = Session("Username")
lblLastSession.Text = Session("LastActive")
lblTotalUsers.Text = Application("TotalActiveUsers")

We keep track of the number of active users by simply incrementing the value every time the login method succeeds, and decrementing the value every time session_end event occurs.

Better means to do this can also be used. The idea of this article is only to communicate the logic.

Testing the Project

Before testing the project, we should check the following.

We keep the domainname as constant, rather than taking it from the user as an input. Check whether proper domain name is assigned to the constant.

VB
Private Const domainName = "TestDomain"

Check whether location of the DLLs that are being imported are proper.

VB
<DllImport("C:\\WINDOWS\\System32\\advapi32.dll")>

Check whether the logoff page has the correct page name and path to transfer the user, once cleanup is done.

VB
Server.Transfer("webform1.aspx")

Code-Care

Care has to be taken that code implemented doesn't allow for inappropriate usage through various userLogins.

I preferred to keep the domain name hard-coded into the application through a constant rather than accept it as an user input... so that it's easy to limit or monitor user login sessions.

In case of intranet projects, we can create a separate domain, and user group for the project and use the above logic to allow users to login to the system only on the particular domain. May be, you can call this an 'Idea' :o)

Using the Controls on Another Web Project

To implement the web user controls in a web project, we simply copy the files related to the two controls, the loginuser class, the logoff user page, to our new web project, and also copy the code from our global.asax.vb to the new project's global.asax.vb.

In VS.NET, these copied files can easily be included in the target project by right clicking and selecting 'Include in Project' in Solution Explorer.

Code Extensibility

The code that's been worked out in this article will authenticate users on only one page of the web application. Normally, a web application will have content inside the site to be viewed by authenticated users... in this case, the controls will have to have a mechanism of holding the user's authentication across page requests. This can be done by holding the windowsIdentity object of the authenticated user in a session variable, and allowing users rights on pages by using FileIOPermission and other classes in the System.Security namespace.

License

This article has no explicit license attached to it, but may contain usage terms in the article text or the download files themselves. If in doubt, please contact the author via the discussion board below.

A list of licenses authors might use can be found here.



Comments and Discussions

 
Generalcan't run on server Pin
suwitk092-Jul-07 23:49
suwitk092-Jul-07 23:49 
GeneralThanks Pin
Hossein khadem11-May-07 22:58
Hossein khadem11-May-07 22:58 
Questionhow to take User's Full Name from Active Directory [modified] Pin
kpsetty28-May-06 20:36
kpsetty28-May-06 20:36 
GeneralToken cannot be zero Pin
Member 183920116-May-05 10:07
Member 183920116-May-05 10:07 
GeneralRe: Token cannot be zero Pin
mangia3-Jun-05 20:05
mangia3-Jun-05 20:05 
AnswerRe: Token cannot be zero Pin
rub2en327-Apr-06 5:36
rub2en327-Apr-06 5:36 
GeneralIIS/WSS logon parsing Pin
Sarma Pisapati16-Sep-04 8:58
Sarma Pisapati16-Sep-04 8:58 
GeneralIIS/WSS logon parsing Pin
Sarma Pisapati16-Sep-04 8:56
Sarma Pisapati16-Sep-04 8:56 
GeneralUPN format Pin
ssdotnet17-Aug-04 16:33
ssdotnet17-Aug-04 16:33 
GeneralRe: UPN format Pin
Anonymous19-Aug-04 4:15
Anonymous19-Aug-04 4:15 
Questionwhat about sharepoint Pin
Anonymous26-Apr-04 22:03
Anonymous26-Apr-04 22:03 
AnswerRe: what about sharepoint Pin
jensjuul22-Jun-05 20:58
jensjuul22-Jun-05 20:58 
GeneralNote: Points to this article (by author) Pin
User 3073524-Mar-04 4:42
professionalUser 3073524-Mar-04 4:42 
GeneralRe: Note: Points to this article (by author) Pin
raam_kimi5-May-06 3:14
raam_kimi5-May-06 3:14 
GeneralLogon credential encryption. Pin
Ken Varn19-Mar-04 5:09
sussKen Varn19-Mar-04 5:09 
I like your idea, but it does not address the issue of encryption of the logon credentials. If you use a web form to ask for the logon and password, this information will be sent as clear text and thus could lead to a compromise of the web site security. Granted you could use SSL, but now you have to purchase a SSL certificate. Using the Windows logon prompt eliminates the need for encryption of the web form data because it is handled by the OS's NTLM or Kerberos security layers through the OS user interface. I don't really care for using this type of solution, because it forces the browser environment to adhere to only be on Windows platforms that support multiple logons.

If you can figure out a way to incorporate your solution with logon credential encryption, I would be very interested in using it.
GeneralRe: Logon credential encryption. Pin
User 3073524-Mar-04 4:38
professionalUser 3073524-Mar-04 4:38 
GeneralRe: Logon credential encryption. Pin
WillemM13-Feb-05 2:12
WillemM13-Feb-05 2:12 
QuestionWill it work if the user can't logon to the webserver? Pin
chony28-Feb-04 3:57
chony28-Feb-04 3:57 
AnswerRe: Will it work if the user can't logon to the webserver? Pin
User 3073524-Mar-04 4:29
professionalUser 3073524-Mar-04 4:29 
Generallogon to local domain Pin
mymmb17-Jan-04 20:31
mymmb17-Jan-04 20:31 
GeneralRe: logon to local domain Pin
User 3073524-Mar-04 4:45
professionalUser 3073524-Mar-04 4:45 
QuestionIs there a catch? Pin
Rocky Moore27-Nov-03 16:03
Rocky Moore27-Nov-03 16:03 
GeneralVery Interesting! Pin
nezza25-Nov-03 22:54
nezza25-Nov-03 22:54 
GeneralRe: Very Interesting! Pin
User 3073526-Nov-03 1:42
professionalUser 3073526-Nov-03 1:42 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.