Results 1 to 8 of 8

Thread: Custom Login Authentication

  1. #1

    Thread Starter
    Super Moderator Wokawidget's Avatar
    Join Date
    Nov 2001
    Location
    Headingly Occupation: Classified
    Posts
    9,632

    Custom Login Authentication

    Unzip the code from the zip file, and create a VD in IIS called CustomAuthenticationDemo2003, which points at the dir you just unzipped.

    This example uses cookies again, but this time we manually set them up. This gives you a little more contol as you can add time out limits.

    All pages inherit my base page, which is:
    VB Code:
    1. Public Class MyBasePage
    2.     Inherits System.Web.UI.Page
    3.  
    4.     Public Sub ValidateLogin()
    5.         Dim Cookie As HttpCookie = Request.Cookies.Item("SECURITY")
    6.         If Cookie Is Nothing Then
    7.             Dim RedirectPage As String = Page.ToString.Substring(4).Replace("_", ".")
    8.             Response.Redirect("Login.aspx?Redirect=" & RedirectPage)
    9.         End If
    10.     End Sub
    11.  
    12.     Public ReadOnly Property Username() As String
    13.         Get
    14.             Dim Cookie As HttpCookie = Request.Cookies.Item("SECURITY")
    15.             If Not (Cookie Is Nothing) Then
    16.                 Return Cookie.Values.Item("USERNAME")
    17.             End If
    18.         End Get
    19.     End Property
    So in your web site your pages inherit MyBaseClass.
    If in the Page Load event of a form if you want to secure it from unauthorised users just add:
    VB Code:
    1. MyBase.ValidateLogin()
    As you can see from the above base page code that if the cookie doesn't exist then you get redirected to the login page. I have added a little bit of code in there for a redirect once you have logged in. This is very rough code and has some problems, ie it doesn't cater for querystrings, but it's only for an example anyways.

    In the login.aspx page we have the login code:
    VB Code:
    1. Private Sub Login(ByVal Username As String, ByVal Password As String)
    2.         If ValidateLogin(Username, Password) Then
    3.             Dim Cookie As New HttpCookie("SECURITY")
    4.             Cookie.Values.Add("USERNAME", Username)
    5.             Response.Cookies.Add(Cookie)
    6.             Dim RedirectPage As String = Request.QueryString.Item("Redirect")
    7.             If RedirectPage = String.Empty Then
    8.                 RedirectPage = "Main.aspx"
    9.             End If
    10.             Response.Redirect(RedirectPage)
    11.         End If
    12.     End Sub
    As you can see if the login is validated then a new cookie is created that stores the username. This is a session based cookie.

    This where it's slightly better at Forms Auth as we can now add a timeout period onto the site.
    So say if our user didn't access the site for say 20 minutes, we would want their session to timeout. This can be done by adding:
    VB Code:
    1. Cookie.Expires = Date.Now.AddMinutes(20)
    just after you've decalred it.

    One good thing about this method is that it can be easily changed. Maybe u don't want to use cookies. Maybe you want to use SQL server and store session GUIDs, which is what we do at work. Personally I prefer the cookie method. Bu the SQL sevrer way does have it's advantages.

    Woka
    Attached Files Attached Files

  2. #2

    Thread Starter
    Super Moderator Wokawidget's Avatar
    Join Date
    Nov 2001
    Location
    Headingly Occupation: Classified
    Posts
    9,632

    Re: Custom Login Authentication

    Just to add a little extra bit of code I decided to change the validate login function in both examples to show you how to connect and validate from an SQL db.
    Just replace the function with:
    VB Code:
    1. Private Function ValidateLogin(ByVal Username As String, ByVal Password As String) As Boolean
    2.         Dim Conn As New SqlClient.SqlConnection("Your connection string here")
    3.         Dim SQL As String
    4.  
    5.         SQL = "SELECT Password "
    6.         SQL &= "FROM Users "
    7.         SQL &= "WHERE Username = @Username "
    8.  
    9.         Dim Comm As New SqlClient.SqlCommand(SQL, Conn)
    10.         Dim Param As New SqlClient.SqlParameter("@Username", SqlDbType.VarChar)
    11.         Param.Direction = ParameterDirection.Input
    12.         Param.Value = Username
    13.  
    14.         Comm.Parameters.Add(Param)
    15.  
    16.         Dim da As New SqlClient.SqlDataAdapter(Comm)
    17.         Dim dt As New DataTable
    18.  
    19.         da.Fill(dt)
    20.  
    21.         Conn.Close()
    22.         Conn.Dispose()
    23.  
    24.         Dim Validated As Boolean
    25.  
    26.         If dt.Rows.Count > 0 Then
    27.             Validated = (dt.Rows.Item(0).Item("Password").ToString = Password)
    28.         End If
    29.  
    30.         Return Validated
    31.     End Function
    Added password encryption may be a good idea, but I left this out to keep the example basic.

    Woof

  3. #3

    Thread Starter
    Super Moderator Wokawidget's Avatar
    Join Date
    Nov 2001
    Location
    Headingly Occupation: Classified
    Posts
    9,632

    Re: Custom Login Authentication

    One of the small problems with the latter example is that the cookie lasts 20 minutes. OK, yea this good, it's what we want. But what we don't want is for them to close IE down walk away from their computer and then someone else browsing to the site, and oh great, the cookie still lets them in. Doh!

    This can be achieved by added a value to the session state.
    In the Global.asax file I have:
    VB Code:
    1. Sub Session_Start(ByVal sender As Object, ByVal e As EventArgs)
    2.         Session.Item("VALIDATED") = False
    3.     End Sub
    So, when someone opens a new session, and browses to the site, the session varible "VALIDATED" gets set to False.

    So when someone logs in I want to set this to True.
    I do this by doing the following in the login function in Login.aspx:
    VB Code:
    1. 'rest of code
    2. End If
    3.  
    4. Session.Item("VALIDATED") = True 'I added this line
    5.  
    6. Response.Redirect(RedirectPage)
    7. 'rest of code
    Now in our base class we need to check for this. So I changed the ValidateLogin function to:
    VB Code:
    1. Public Sub ValidateLogin()
    2.         Dim Cookie As HttpCookie = Request.Cookies.Item("SECURITY")
    3.         Dim Validated As Boolean
    4.         If Not (Cookie Is Nothing) Then
    5.             Validated = CType(Session.Item("VALIDATED"), Boolean)
    6.         End If
    7.         If Not Validated Then
    8.             Dim RedirectPage As String = Page.ToString.Substring(4).Replace("_", ".")
    9.             Response.Redirect("Login.aspx?Redirect=" & RedirectPage)
    10.         End If
    11.     End Sub
    This now checks for the session varible.

    I have no idea if this is the correct way to go about this or not, but it works, so I am happy for now.

    Please find the project attached.

    WOka
    Attached Files Attached Files

  4. #4

    Thread Starter
    Super Moderator Wokawidget's Avatar
    Join Date
    Nov 2001
    Location
    Headingly Occupation: Classified
    Posts
    9,632

    Re: Custom Login Authentication

    Here's the next installment

    I have changed the Validate login function in the MyBaseClass class.
    This change now handles redirects with query strings.
    The code is:
    VB Code:
    1. If Not Validated Then
    2.             Dim Query As String = String.Empty
    3.             For Index As Integer = 0 To Request.QueryString.Count - 1
    4.                 If Query.Length > 0 Then
    5.                     Query &= "&"
    6.                 End If
    7.                 Query &= Request.QueryString.Keys.Item(Index)
    8.                 Query &= "="
    9.                 Query &= Request.QueryString.Item(Index)
    10.             Next Index
    11.  
    12.             Dim RedirectPage As String = Page.ToString.Substring(4).Replace("_", ".")
    13.  
    14.             If Query.Length > 0 Then
    15.                 RedirectPage &= "?" & Query
    16.             End If
    17.             RedirectPage = Server.UrlEncode(RedirectPage)
    18.             Response.Redirect("Login.aspx?Redirect=" & RedirectPage)
    19.         End If
    I also added Server.Decode in the Login page to decode the "redirect" query string. I had to encode it because you cannot have a query string in a query string as it would look like:
    Code:
    ?Redirect=Users.aspx?ID=5&Task=Delete
    ASP.NET would read this as 3 different query strings, the 1st being "Users.aspx?". For this reason we have to URL encode it.

    Again, I am not sure if this is the correct way to get the query string, but I don't know of any simpler way to get it

    Attached is the new updated project.

    Wooof
    Attached Files Attached Files

  5. #5

    Thread Starter
    Super Moderator Wokawidget's Avatar
    Join Date
    Nov 2001
    Location
    Headingly Occupation: Classified
    Posts
    9,632

    Re: Custom Login Authentication

    OK...I've changed it again.
    It now, instead of forcing you to the login page, gives you the option to force to a login page.
    The base class has changed to:
    VB Code:
    1. Public Function ValidateLogin(ByVal ForceLogin As Boolean) As Boolean
    2.         Dim Cookie As HttpCookie = Request.Cookies.Item("SECURITY")
    3.         Dim Validated As Boolean
    4.         If Not (Cookie Is Nothing) Then
    5.             Validated = CType(Session.Item("VALIDATED"), Boolean)
    6.         End If
    7.         If Not Validated And ForceLogin Then
    8.             Login()
    9.         Else
    10.             Return Validated
    11.         End If
    12.     End Function
    13.  
    14.     Public Sub Login()
    15.         Response.Redirect("Login.aspx?Redirect=" & Server.UrlEncode(CurrentURL))
    16.     End Sub
    17.  
    18.     Public ReadOnly Property CurrentURL() As String
    19.         Get
    20.             Return Request.Url.PathAndQuery
    21.         End Get
    22.     End Property
    This means I can do the following in my main pages:
    VB Code:
    1. Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    2.         If MyBase.ValidateLogin(False) Then
    3.             btnLogin.Visible = False
    4.             Response.Write("Hello " & MyBase.Username & ", your task today is " & MyBase.GetQueryString("Task", "***Unknown***"))
    5.         Else
    6.             btnLogin.Visible = True
    7.         End If
    8.     End Sub
    9.  
    10.     Private Sub btnLogin_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLogin.Click
    11.         MyBase.Login()
    12.     End Sub
    The above code is only an example. Maybe you want someone to view pages regardless of if they are logged in or not, but if they arn't you want to disable functionality, or show them a different control.
    You can still force a login by doing:
    VB Code:
    1. MyBase.ValidateLogin(True)
    I have also added some querystring functions to the base class to help my pages retieve the correct querystring in the correct format.

    The code attached contains the new changes.

    Woof
    Attached Files Attached Files

  6. #6

    Thread Starter
    Super Moderator Wokawidget's Avatar
    Join Date
    Nov 2001
    Location
    Headingly Occupation: Classified
    Posts
    9,632

    Re: Custom Login Authentication

    OK. here's the next version.
    I have it validating a domian user's password.
    This code does not impersonate a windows user, I removed that code to make it a little more simple.
    All it does is validates the domain users password...I believe. I am still trying to look up more info on the API function:
    VB Code:
    1. Private Declare Function LogonUserA 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

    I have moved all the user validation code to a class called Authorisation, just to keep the code neat and in one place. I have also added an enum:
    VB Code:
    1. Public Enum LoginMode
    2.         Database = 0
    3.         HardCoded = 1
    4.         Windows = 2
    5.     End Enum
    Which is used when calling the ValidateUser method in the Authentication class, the ValidateUser function is:
    VB Code:
    1. Public Function ValidateLogin(ByVal Username As String, ByVal Password As String, ByVal AuthenticationMethod As LoginMode) As Boolean
    2.         Select Case AuthenticationMethod
    3.             Case LoginMode.Database
    4.                 Return ValidateDBLogin(Username, Password)
    5.             Case LoginMode.HardCoded
    6.                 Return ValidateHardCodedLogin(Username, Password)
    7.             Case LoginMode.Windows
    8.                 If Username.IndexOf("\") > 0 Then
    9.                     Dim LoginDetails() As String = Username.Split("\"c)
    10.                     Return ValidateWindowsLogin(LoginDetails(0), LoginDetails(1), Password)
    11.                 End If
    12.         End Select
    13.     End Function
    I have prely done this enum for this demo. In the real world you would just pick one of those methods and ignore the rest.

    When logging into a domain your username must be in the format DOMAIN\Username.
    This then gets split up into it's individual bits when sent to the ValidateWindowsLogin function.

    RobDog, I know you wanted this as a way to login, but do you want to impersonate a user, so that you can get access to resources on say the network etc...? I personally can't see the need for this and would find it pointless for what I want to do with my intranet...not sure about you.

    To change the method of authentication go into the Login.aspx page and change the Login function to pass a different enum to the authentication class.

    Woka
    Attached Files Attached Files

  7. #7

    Thread Starter
    Super Moderator Wokawidget's Avatar
    Join Date
    Nov 2001
    Location
    Headingly Occupation: Classified
    Posts
    9,632

    Re: Custom Login Authentication

    Thanks to Alex_Read and Matt3011 for there help with this.
    For authenticating a login against an active directory you can use:
    VB Code:
    1. Private Function ValidateActiveDirectoryLogin(ByVal Domain As String, ByVal Username As String, ByVal Password As String) As Boolean
    2.  
    3.         Dim Success As Boolean = False
    4.  
    5.         Dim Entry As New System.DirectoryServices.DirectoryEntry("LDAP://" & Domain, Username, Password)
    6.         Dim Searcher As New System.DirectoryServices.DirectorySearcher(Entry)
    7.         Searcher.SearchScope = DirectoryServices.SearchScope.OneLevel
    8.         Try
    9.             Dim Results As System.DirectoryServices.SearchResult = Searcher.FindOne
    10.             Success = Not (Results Is Nothing)
    11.         Catch
    12.             Success = False
    13.         End Try
    14.  
    15.         Return Success
    16.  
    17.     End Function
    You have to reference the System.DirectorySevices in your application.
    OK...I have now removed the old code that authenticated a windows account and replaced it with the above code.

    I have attached the full updated project to this post.

    Woof
    Attached Files Attached Files

  8. #8

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width