ASP.NET Login page example with Remember me Option

ASP.NET Login page example with Remember me Option

During we develop a product its always wise to save user time. Think about a login page. Here for Consecutive logins it is much better if we will store user Login Credentials. Using which System will remember the user id and password for next login. In this demo app I am creating a ASP.NET login page with “Remember me” Option.

The logic behind is so simple “During a user login to the System I am storing his/her user id and password to a Cookie. Then under page load event checking is Cookie exists. If so taking user id and password from the Cookie”.

Login.aspx

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Login.aspx.vb" Inherits="Login" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Demo Login App</title>
<style type="text/css">
#frmLogin { max-width: 300px; margin: 0 auto; padding-top: 120px; }
.formControl { font-family: Verdana; font-size: 12px; }
.loginDiv { width:300px; margin-top: 20px; padding: 20px 20px 20px 20px; background-color: #f7f7f7; -moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); -webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); } 
.rounded { border-radius: 10px; -moz-border-radius: 10px; -webkit-border-radius: 10px; }
</style>
</head>
<body>
<form id="frmLogin" runat="server">
<div class="loginDiv rounded">
<div class="formControl">
Email ID&nbsp;<span style="color: Red;">*</span>
</div>
<div class="formControl">
<asp:TextBox ID="txtEmailID" runat="server" Width="100%"></asp:TextBox>
<asp:RequiredFieldValidator ID="rfvEmailID" runat="server" ControlToValidate="txtEmailID"
Display="Dynamic" ErrorMessage="Email should not be blank.<br />"></asp:RequiredFieldValidator>
<asp:RegularExpressionValidator ID="revEmailID" runat="server" ControlToValidate="txtEmailID"
Display="Dynamic" ErrorMessage="Enter a valid Email ID.<br />" ValidationExpression="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*"></asp:RegularExpressionValidator>
</div>
<div class="formControl">
Password&nbsp;<span style="color: Red;">*</span>
</div>
<div class="formControl">
<asp:TextBox ID="txtPassword" runat="server" TextMode="Password" Width="100%"></asp:TextBox>
<asp:RequiredFieldValidator ID="rfvPassword" runat="server" ControlToValidate="txtPassword"
Display="Dynamic" ErrorMessage="Password should not be blank."></asp:RequiredFieldValidator>
</div>
<asp:Button ID="btnVisitorLogin" runat="server" Text="Login" />
<asp:Label ID="lblMsg" runat="server"></asp:Label>
<asp:CheckBox ID="chkNextLogin" runat="server" />&nbsp;Remember me<a href="#" class="pull-right margin-gap">Need
help?</a>
</div>
</form>
</body>
</html>

For security reason in Code behind I added my EncryDecry.vb Class from app_code/vb. To execute vb code inside vb folder of app_code I Configured my web.config.

Login.aspx.vb

Imports System.Web.Security
Imports System.Data
Imports System.Data.SqlClient
Partial Class Login
Inherits System.Web.UI.Page
Dim LoginSqlConn As New SqlConnection(ConfigurationManager.AppSettings.Get("DBKey").ToString())
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
txtEmailID.Focus()
'Check if the browser support cookies
If Request.Browser.Cookies Then
'Check if the cookies with name PBLOGIN exist on user's machine
If Request.Cookies("PBLOGIN") IsNot Nothing Then
'Pass the user name and password to the VerifyLogin method
Me.VerifyLogin(Request.Cookies("PBLOGIN")("UNAME").ToString(), Request.Cookies("PBLOGIN")("UPASS").ToString())
End If
End If
End If
End Sub
Protected Sub btnVisitorLogin_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnVisitorLogin.Click
'Decrypt the Password & UserID from Database
Dim EncrDecr As New EncryDecry
'Validation Checking Aginest Submission
If rfvPassword.IsValid And rfvEmailID.IsValid Then
'Clear Invalid login Message Label
lblMsg.Text = ""
'Temporary SecuredUniqueKey
Dim UniKey As String = "FCPH6-BPK27-2V4MR"
'Login Checking command in shape of a Stored Procedure that returns Record Count
Dim LoginCommand As New SqlCommand("USP_LoginCheck", LoginSqlConn)
LoginCommand.CommandType = CommandType.StoredProcedure
'Pass Parameter to Stored Procedure
LoginCommand.Parameters.Add("@UserID", SqlDbType.NVarChar, 256).Value = EncrDecr.TripleDESEncode(Trim(txtEmailID.Text), "RC2")
LoginCommand.Parameters.Add("@Passcode", SqlDbType.NVarChar, 256).Value = EncrDecr.TripleDESEncode(Trim(txtPassword.Text), "RC2")
LoginCommand.Parameters.Add("@SecuredUniqueKey", SqlDbType.NVarChar, 256).Value = UniKey
LoginCommand.Parameters.Add("@Status", SqlDbType.NVarChar, 20).Value = "Active"
Dim RecordCNT As Integer = 0
Try
Dim LoginDataReader As SqlDataReader
LoginSqlConn.Open()
LoginDataReader = LoginCommand.ExecuteReader
If LoginDataReader.Read Then
RecordCNT = Convert.ToInt32(LoginDataReader(0).ToString())
End If
Catch ex As Exception
Response.Write(ex.ToString())
Finally
LoginSqlConn.Close()
End Try
'Login Checking using the return int value of USP_LoginCheck stored procedure
If (RecordCNT = 1) Then
Me.VerifyLogin(EncrDecr.TripleDESEncode(Trim(txtEmailID.Text), "RC2"), EncrDecr.TripleDESEncode(Trim(txtPassword.Text), "RC2"))
ElseIf (RecordCNT > 1) Then
lblMsg.Text = "Invalid Login Credentials"
'Implement 5 Login Attempts of Account Lock
ElseIf (RecordCNT < 1) Then
lblMsg.Text = "Invalid Login Credentials"
'Implement 5 Login Attempts of Account Lock
End If
End If
End Sub
Private Sub VerifyLogin(ByVal UserID As String, ByVal Password As String)
Dim LoginDetailsCommand As New SqlCommand("USP_LoginDetails", LoginSqlConn)
LoginDetailsCommand.CommandType = CommandType.StoredProcedure
'Pass Parameter to Stored Procedure
LoginDetailsCommand.Parameters.Add("@UserID", SqlDbType.NVarChar, 256).Value = UserID
LoginDetailsCommand.Parameters.Add("@Passcode", SqlDbType.NVarChar, 256).Value = Password
Try
Dim LoginDetailsDR As SqlDataReader
LoginSqlConn.Open()
LoginDetailsDR = LoginDetailsCommand.ExecuteReader
If LoginDetailsDR.Read Then
Session("UserID") = LoginDetailsDR("PkUid")
Session("UserEmail") = UserID
Session("FirstName") = LoginDetailsDR("FirstName")
Session("LastName") = LoginDetailsDR("LastName")
Session("RootPath") = Server.MapPath("../")
'Using form authentication redirect the page to the Default.aspx
FormsAuthentication.RedirectFromLoginPage(Trim(txtEmailID.Text), True)
'check if remember me checkbox is checked on login
If (chkNextLogin.Checked) Then
'Check if the browser support cookies
If (Request.Browser.Cookies) Then
'Check if the cookie with name PBLOGIN exist on user's machine
If (Request.Cookies("PBLOGIN") Is Nothing) Then
'Create a cookie with expiry of 30 days
Response.Cookies("PBLOGIN").Expires = DateTime.Now.AddDays(30)
'Write username to the cookie
Response.Cookies("PBLOGIN").Item("UNAME") = UserID
'Write password to the cookie
Response.Cookies("PBLOGIN").Item("UPASS") = Password
Else
'If the cookie already exist then wirte the user name and password on the cookie
Response.Cookies("PBLOGIN").Item("UNAME") = UserID
Response.Cookies("PBLOGIN").Item("UPASS") = Password
End If
End If
End If
Else
lblMsg.Text = "Invalid Login Credentials"
End If
Catch ex As Exception
Response.Write(ex.ToString())
Finally
LoginSqlConn.Close()
End Try
End Sub
End Class

web.config

<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="DBKey" value="Data Source=VIJAYSHANTI; uid=sa; pwd=tiger; database=CodeRND;"/>
</appSettings>
<connectionStrings/>
<system.web>
<compilation debug="true" strict="false" explicit="true">
<codeSubDirectories>
<add directoryName="VB"/>
</codeSubDirectories>
</compilation>
<authentication mode="Windows"/>
</system.web>
</configuration>

EncryDecry is the class which helps to convert user id and password to RC2 format. In-case an other user find out the cookie in client machine he or she can’t able to hack the original user.

EncryDecry.vb

Imports System.Security.Cryptography
Imports Microsoft.VisualBasic
Public Class EncryDecry
Public Function TripleDESEncode(ByVal value As String, ByVal key As String) As String
Dim des As New System.Security.Cryptography.TripleDESCryptoServiceProvider
des.IV = New Byte(7) {}
Dim pdb As New System.Security.Cryptography.PasswordDeriveBytes(key, New Byte(-1) {})
des.Key = pdb.CryptDeriveKey("RC2", "MD5", 128, New Byte(7) {})
Dim ms As New IO.MemoryStream((value.Length * 2) - 1)
Dim encStream As New System.Security.Cryptography.CryptoStream(ms, des.CreateEncryptor(), System.Security.Cryptography.CryptoStreamMode.Write)
Dim plainBytes As Byte() = Text.Encoding.UTF8.GetBytes(value)
encStream.Write(plainBytes, 0, plainBytes.Length)
encStream.FlushFinalBlock()
Dim encryptedBytes(CInt(ms.Length - 1)) As Byte
ms.Position = 0
ms.Read(encryptedBytes, 0, CInt(ms.Length))
encStream.Close()
Return Convert.ToBase64String(encryptedBytes)
End Function
Public Function TripleDESDecode(ByVal value As String, ByVal key As String) As String
Dim des As New System.Security.Cryptography.TripleDESCryptoServiceProvider
des.IV = New Byte(7) {}
Dim pdb As New System.Security.Cryptography.PasswordDeriveBytes(key, New Byte(-1) {})
des.Key = pdb.CryptDeriveKey("RC2", "MD5", 128, New Byte(7) {})
Dim encryptedBytes As Byte() = Convert.FromBase64String(value)
Dim ms As New IO.MemoryStream(value.Length)
Dim decStream As New System.Security.Cryptography.CryptoStream(ms, des.CreateDecryptor(), System.Security.Cryptography.CryptoStreamMode.Write)
decStream.Write(encryptedBytes, 0, encryptedBytes.Length)
decStream.FlushFinalBlock()
Dim plainBytes(CInt(ms.Length - 1)) As Byte
ms.Position = 0
ms.Read(plainBytes, 0, CInt(ms.Length))
decStream.Close()
Return Text.Encoding.UTF8.GetString(plainBytes)
End Function
End Class