Guest Author: Pang Tat Sean
In ASP.NET, most of the tedious work of writing authentication form has been taken out. When user logs in using form authentication, a cookie is created and used to track the user throughout the site. Once user successfully logs in, you can issue an authentication cookie to save authenticated users from having to login every time they visit new page of your website. The cookie will expire when browser is closed.
Since many examples on the Internet for Form Authentication hover around use either database or web.config to store user maes and passwords, I have decided to write an example of how to create ASP.NET Authentication form using XML file for storing user information instead of Microsoft SQL Server or Microsoft Access database. I use the 'Code Behind' approach to separate the presentation layer from the logic layer and make the code more reusable. However, this is just a simple example and sure if want to use it in your own projects, there are some things here and there you need to change/add.
Web.config
<configuration>
<System.web>
<authentication mode="Forms">
<forms name=".ASPXFORMSTEST"
loginUrl="login.aspx"
protection="All"
path="/" timeout="30" />
</authentication>
<authorization>
<deny users="?" />
<allow users="*" />
</authorization>
</System.web>
</configuration>
Users.xml
<?xml version="1.0"?>
<users>
<pang>A15F69189FDD3C0A64F82C0AD73C319020351978</pang>
</users>
Default.aspx
<%@ Page Language="VB" %>
<script runat="server">
' Insert page code here
</script>
<html>
<head>
</head>
<body text="#000000" bgcolor="green">
<form runat="server">
<% response.write("Ya! You got the right password!!!") %>
</form>
</body>
</html>
Login.aspx
<%@ Page Language="vb" Src="Login.vb" Inherits="UserLogin" %>
<script runat="server">
Sub ProcessAdd(byval sender as Object, byval e as EventArgs)
response.redirect("AddLogin.aspx")
End Sub
</script>
<html>
<head>
<title>Custom Forms Authentication Login Form</title>
</head>
<body text="#000000" bgcolor="#ffffff">
<form runat="server">
<table cellspacing="0" cellpadding="0" width="400" border="0">
<tbody>
<tr>
<td>
Username :
</td>
<td>
</td>
<td>
<asp:TextBox id="txtUser"
runat="server"></asp:TextBox>
</td>
</tr>
<tr>
<td>
Password :
</td>
<td>
</td>
<td>
<asp:TextBox id="txtPassword" runat="server"
TextMode="Password">
</asp:TextBox>
</td>
</tr>
<tr>
</tr>
<tr>
<td>
</td>
<td>
</td>
<td>
<asp:CheckBox id="chkPersistLOgin"
runat="server"></asp:CheckBox>
Remember my Credential
</td>
</tr>
<tr>
<td>
</td>
<td>
</td>
<td>
<asp:LinkButton id="lBAdd" onclick="ProcessAdd"
runat="server" Text="Add User"></asp:LinkButton>
</td>
</tr>
<tr>
<td>
</td>
<td>
</td>
<td>
<br />
<asp:Button id="cmdLogin" onclick="ProcessLogin"
runat="server" Text="Login"></asp:Button>
</td>
</tr>
</tbody>
</table>
<br />
<br />
</form>
<asp:label id="ErrorMessage" runat="server"></asp:label>
</body>
</html>
Login.vb
Imports System
Imports System.Data.SqlClient
Imports System.Web.Security
Imports System.xml
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports Microsoft.VisualBasic
Public Class UserLogin
Inherits System.Web.UI.Page
Public txtUser as textbox
Public txtPassword as textbox
Public chkPersistLogin as CheckBox
Public cmdLogin as Button
Public ErrorMessage as label
Public Sub ProcessLogin(objSender As Object, objArgs As EventArgs)
' This will return the full physical path of login.aspx
Dim strCurrPath As String = Request.PhysicalPath
' In Order to get the full path of users.xml, we need to use [InStrRev]
' function to replace the [login.aspx] with [users.xml] in order to get
' the
' full physical path for users.xml
Dim strXMLDoc As String = Left(strCurrPath,InStrRev(strCurrPath, _
"\")) & "users.xml"
Dim strUser As String = txtUser.Text
Dim strPassword As String = txtPassword.Text
' hash the password by calling GetHashedPass function
Dim strEncPassword As String = GetHashedPass(strPassword)
Dim blnIsAuthenticated As Boolean
' Create the XMLDocument
Dim objXMLDoc As New XMLDocument()
Errormessage.text = ""
Try
' Load the XML Document
objXMLDoc.Load(strXMLDoc)
Catch err As Exception
ErrorMessage.Text = "<b> The XML Document can not be " _
& "loaded.</b>.<br>" & err.Message & "<br />" & err.Source
Exit Sub
End Try
Dim nodeList As XmlNodeList
' creates a [XmlDocument] object and uses the [GetElementsByTagName]
' method and the resulting [XmlNodeList] to display the password
' and verify it with the password entered by user
nodeList = objXMLdoc.GetElementsByTagName(strUser)
'see if we found an element with this username
If Not nodeList Is Nothing Then
Dim blnUserExists As Boolean = True
Dim strUserCheck As String
Try
strUserCheck = nodeList(0).FirstChild().Value
Catch objError As Exception
ErrorMessage.Text = "<b>Invalid username</b> please " _
& "re-enter..."
blnUserExists = False
End Try
If blnUserExists = True Then
If strEncPassword = nodeList(0).FirstChild().Value Then
blnIsAuthenticated = True
Else
ErrorMessage.TExt = "<b>Invalid password</b> please " _
& "re-enter..."
End If
End if
End If
If blnIsAuthenticated Then
FormsAuthentication.RedirectFromLoginPage( _
strUser,chkPersistLogin.Checked)
End If
End Sub
Public Function GetHashedPass(ByVal aPassword As String) As String
' Using [FormsAuthentication.HashPasswordForStoringInConfigFile]
' method
' to hash the password .
' First parameter : the password to hash
' Second parameter : password format(algorithms) ; either are "sha1"
' or "md5"
Return FormsAuthentication.HashPasswordForStoringInConfigFile( _
aPassword,"sha1")
End Function
End Class
AddLogin.aspx
<%@ Page Language="vb" Src="AddUser.vb" Inherits="AddUser" %>
<html>
<head>
<title>Custom Forms Authentication Login Form</title>
</head>
<body text="#000000" bgcolor="#ffffff">
<form runat="server">
<table cellspacing="0" cellpadding="0" width="400" border="0">
<tbody>
<tr>
<td>
Username :
</td>
<td>
</td>
<td>
<asp:TextBox id="txtUser"
runat="server"></asp:TextBox>
</td>
</tr>
<tr>
<td>
Password :
</td>
<td>
</td>
<td>
<asp:TextBox id="txtPassword" runat="server"
TextMode="Password">
</asp:TextBox>
</td>
</tr>
<tr>
<td>
</td>
<td>
</td>
<td>
<br />
<asp:Button id="cmdLogin" onclick="ProcessLogin"
runat="server" Text="Add User"></asp:Button>
</td>
</tr>
</tbody>
</table>
<br />
<br />
<asp:label id="ErrorMessage" runat="server"></asp:label>
</form>
</body>
</html>
AddUser.vb
Imports System
Imports System.Data.SqlClient
Imports System.Web.Security
Imports System.xml
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports Microsoft.VisualBasic
Public Class AddUser
Inherits System.Web.UI.Page
Public txtUser as textbox
Public txtPassword as textbox
Public cmdLogin as Button
Public ErrorMessage as label
Public Sub ProcessLogin(objSender As Object, objArgs As EventArgs)
try
Dim strEncPass As String
Dim nextnode As XmlNode
' Create the [xmlDocument]
Dim xmldoc As New System.Xml.XmlDocument()
' This will return the full physical path of AddLogin.aspx
Dim strCurrPath As String = Request.PhysicalPath
' In Order to get the full path of users.xml, we need to use
' [InStrRev]
' function to replace the [AddLogin.aspx] with [users.xml] in
' order to get the
' full physical path for users.xml
Dim strXMLDocPath As String = Left(strCurrPath,InStrRev( _
strCurrPath, "\")) & "users.xml"
' Create an element
Dim elem As XmlElement = xmldoc.CreateElement(txtUser.Text)
' Using [FormsAuthentication.HashPasswordForStoringInConfigFile]
' method
' to hash the password .
' First parameter : the password to hash
' Second parameter : password format(algorithms) ; either are
' "sha1" or "md5"
strEncPass = _
FormsAuthentication.HashPasswordForStoringInConfigFile( _
txtPassword.Text,"sha1")
' Load the xml document file
xmldoc.Load(strXMLDocPath)
' get the nodes for [username]
nextnode = xmldoc.LastChild
' set the [password] for the particular user
elem.InnerText = strEncPass
' Append the [Username] and [password] to the xml document file
nextnode.AppendChild(elem)
' Save the xml Document file
xmldoc.Save(strXMLDocPath)
ErrorMessage.text = " You have successfully add the new user!!!"
Catch ex as Exception
ErrorMessage.text = ex.message
End Try
End Sub
End Class