Saturday, March 24, 2012

Login function using ASP.NET and XML database, help.

Hello,

I've been working on an assignment with my group and is about developing an e-commerce site with simple features using ASP.NET. We have little past experiences in working with ASP.NET so I hope you guys can help us newbies.

I'm trying to make a simple login feature on the index.aspx page that requires user to login with their username and password before clicking "enter" to proceed to the search.aspx page. The username and password info are simply stored in an XML file, with the following format...

XML file -

<CustomerInfo>
<Customer>
<CustomerID>1</CustomerID>
<CustomerName>Name1</CustomerName>
<Username>0001</Username>
<Password>0001</Password>
</Customer>
</CustomerInfo
With a lack of example code given by my lecturer notes, I cannot figure out how to code some of the stuff. I already got the interface done.

<asp:TextBox id="txtUserName" runat="server" width="150"></asp:TextBox>
<asp:TextBox id="txtUserPass" runat="server" Width="150" textmode="Password"></asp:TextBox
<input id="cmdLogin" type="submit" value="Login" name="cmdLogin" runat="server" language="javascript" onclick="return cmdLogin_onclick()"
<asp:label id="lblMsg" runat="server" Font-Size="10" Font-Name="Verdana" ForeColor="red" /
What I need is now how do I get the code for the index.aspx.vb page so when the user enters his/her username and password, the server matches the entered username first to see if there is one in the XML database, then if it's exist (error message if not), match it with the password next to it. (error message if not)

When a user has successfully logged in, their unique CustomerID then have to be stored in a Session variable for use in later modules. (as per instruction in assignment, don't know how to do this..)

Could anyone please help me to get the starting for me to code on? You do not have to code everything for me, I need to learn how to do this anyway. Would be great if anyone could help me in this, and also explain what each line of code does if possible. Thank you.

Code that needs to be worked on: (I think)

Private Sub cmdLogin_ServerClick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdLogin.ServerClick

Dim Username As String = txtUserName.Text
Dim Password As Integer = txtUserPass.Text

??

Get the user record
if user not found
then message invalid user name
else
if password = "password"
redirect to search screen
else
errormessageTo save some typing i will refer you to these 2 artcicles that have code samples to help, ifyou have more questions after dont hesitate to ask ;)...

http://www.15seconds.com/issue/020220.htm
http://www.15seconds.com/issue/020305.htm
First off I would chage the <input> button to an asp:button like so:-

<asp:button id="cmdLogin" runat="server" text="Login"></asp:button
Then your code would be as follows (assuming the customers.xml file is in the same directory


Private Sub cmdLogin_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdLogin.Click
Dim xmldoc As New System.Xml.XmlDocument()
xmldoc.Load(Server.MapPath("customers.xml"))
Dim xmlnodelist As System.Xml.XmlNodeList
xmlnodelist = xmldoc.SelectNodes("/CustomerInfo/Customer[Username='" & txtUserName.Text & "']")
If xmlnodelist.Count > 1 Then
'error more than one of the same username found
'this should not happen
ElseIf xmlnodelist.Count = 0 Then
'username not found
lblMsg.Text = "Username not Found"
Else
Dim xmlel As System.Xml.XmlNode = xmlnodelist.Item(0)
Dim passNode As System.Xml.XmlNode = xmlel.SelectSingleNode("Password")
If passNode.InnerText = txtUserPass.Text Then
'login ok
'redirect to new page ro whatever
Else
lblMsg.Text = "Invalid Password"
End If
End If
End Sub

Frazell -

Thanks a lot for those links. I actually did a bit of searching before I post here, and have seen those before. Unfortunately, it was a little too complex for me. :) But thanks a lot anyway.

BrianOConnel -

Thanks a ton! Those codes work wonder, I got the login system working now. Thanks. However, I do have some more questions.

The assignment required me to..

"Require the customer to login to the system with their unique username and password. (Each customer's Username, Password, CustomerID and other relevant properties are to be stored in and retrieved from an XML database). Customers should not be able to proceed past this page until they have successfully loggin in. When the customer has successfully logged in their unique CustomerID must be stored in a Session variable for use in later modules"

So far, I got the login system working.

But I'm still trying to figure out how to make hyperlink to the search.aspx page do not work and show an error message if the login was unsuccessful. And only works when the login is valid. Shall I make a asp:hyperlink or something?

Also, does the last sentence of the question means when a customer has logged in, they don't have to log in again for the entire session? I'm still not sure how to code that properly.

Thanks again, this question is actually the hardest of the entire assignment, my team has already finished all the other "easier" parts (easy as in we only had to change existing codes given by lecturers), just this one is tricking us. :)
Would anyone help me with this? Too hard for me who was never taught how to code in VB language.
Heres an article that explains Forms Authenitication in .NET. After setting up FormsAuthentication i would use a line of code like this in Form_Load to determine if the user is logged in. In order for this to work you will need to have this in an unprotected folder.


'Holds the Forms Authentication classes as well as other security stuff ;), Import this to make your typing requirement less
Imports System.Web.Security

If user.Identity.IsAuthenticated = False Then
'Add code for handling users who are not authenticated such as redirecting them to a login page
End If

That should allow you to do what ever you need to do for any unautheniticated users ;)...

Does that wrap ya up?
Hello, I've looked at the articles and I can understand what it is trying to do. Essentially they want to verify a user's credentials against the Web.config

However, I do not know how to do this against an XML file.

That code, when placed in an aspx.vb file, it gives me the error that ('Import' statements must precede any declarations)

What I did was, I tried to copy and paste the codes from those articles, login.aspx code to the index.aspx and the default.aspx to the search.aspx. Also changed the asp:textbox IDs to match it with the new codes and added the new checkbox and OnClick="ProcessLogin" in the index.aspx. But while attemping to login, it keeps giving me the 'Something went wrong' message as in the Sub ProcessLogin code. I can imagine how it is not connected to the XML database properly.

For the search.aspx page, using the default.aspx code, well, I think I need to get the login page to work before getting this one to work.

My other question is, so if the codes are made to work, an unauthenciated user trying to access the search.aspx (by clicking on the hyperlink in index.aspx) will run that bit of code you gave me in your last post? Like give them an error message (where does the error message appear?), then redirect them back to index.aspx?

Right now, I hope this is not too complex for my subject. As I'm afraid my lecturer would mark me down for doing more than he asked for. But I need to know if what I'm doing right now is what the lecturer actually wants in the question I last posted.

Thanks for helping again.
Well if I expand on the xml code I posted earlier then assuming this xml login page is called login.aspx and you have put the following into your web.config:-

<authentication mode="Forms">
<forms loginUrl="login.aspx" />
</authentication
then navigating to any page on your site will redirect to login.aspx first. Now in the above code I posted when someone successfully logs in we need to have recorded the customer id for your needs so we would adjust the above code to get the customer id:-


Dim xmlel As System.Xml.XmlNode = xmlnodelist.Item(0)
Dim passNode As System.Xml.XmlNode = xmlel.SelectSingleNode("Password")
dim custIDNode as System.Xml.XmlNode = xmlel.SelectSingleNode("CustomerID")
dim custID as string = custIDNode.InnerText
session("CustID") = custID
If passNode.InnerText = txtUserPass.Text Then
'login ok
'redirect to new page or whatever
FormsAuthentication.RedirectFromLoginPage(txtUserName.Text, true)
Else
lblMsg.Text = "Invalid Password"
End If

The redirectfromloginpage will store the username in a session variable automatically and the true boolean means it will persist for the whole session. Because you want to record the customer id as well then you can manually place it in your own session variable and retrieve it anytime you wish - dim custID as string = session("CustID").tostring
To be honest if I were doing this project I would create a customer class and when somebody logged in I would create a new customer class and store it in the session so I could have quick access to any part of their details.


public class Customer
public customername as string
public customerid as string
public username as string
public password as string

public sub new(cname as string, cid as string, uname as string, pword as string)
customername = cname
customerid = cid
username = uname
password = pword
end sub
end class

Thats a simple class to serve as an exmaple - you would normally make these properties private and create property procedures but it will server to explain what I'm doing.


Dim xmlel As System.Xml.XmlNode = xmlnodelist.Item(0)
Dim passNode As System.Xml.XmlNode = xmlel.SelectSingleNode("Password")
dim custID as string = xmlel.SelectSingleNode("CustomerID").InnerText
dim custName as string = xmlel.SelectSingleNode("CustomerName").InnerText
If passNode.InnerText = txtUserPass.Text Then
'login ok
'redirect to new page or whatever
dim cust as new customer(custName, custID, txtUserName.Text, txtUserPass.Text)
session("CurrentCustomer") = cust
FormsAuthentication.RedirectFromLoginPage(txtUserName.Text, true)
Else
lblMsg.Text = "Invalid Password"
End If

Now I can retrieve the current session's user easily in any page using the following:-

dim cust as customer = ctype(session("CurrentCustomer"), customer)
dim custname as string = cust.customername
....etc.
Hello BrianOConnel, thanks for the help again.

I wanted to keep my code as simple as possible so that I could just answer the assignment question while not providing any extra features that my lecture did not expect me to do (or able to do).

First of all, in the web.config file, I have added the


<authentication mode="Forms">
<forms loginUrl="index.aspx" />
</authentication>

With index.aspx being the login page. There was another set of authentication (window mode) and authorization (allow all user) code in the web.config file, but I have deleted them all.

However, as you have mentioned, adding those previous code will prevent anyone from accessing any other pages in the project before logging in. Unfortunately, it does not seem to work for me, I was still able to access other pages first without going through index.aspx. Or maybe I did not quite understand the code properly?

My friend apparently helped me and wrote this set of code, which has seem to be working so far.


Private Sub cmdLogin_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdLogin.Click

' Declared a dataset (at the top) to retrieve the data in the XML file
dsCustomerXML.ReadXml("C:\Inetpub\wwwroot\DanceCentral\CustomerInfo.xml")
Dim datCust As DataTable = dsCustomerXML.Tables.Item(0)
Dim i As Integer = 0
' Loop through all the rows in the datatable, find the customer
For i = 0 To datCust.Rows.Count - 1
If datCust.Rows.Item(i).Item("Username") = txtUserName.Text Then
'then validate the password

If datCust.Rows.Item(i).Item("Password") = txtUserPass.Text Then
lblMsg.Text = "Login Successful! Proceed to the ordering system."
LoginStatus = True
Else
' bad password, kick out, bye
lblMsg.Text = "Login Error: Please check you user name and password"
LoginStatus = False
End If
End If
Next
' bad login, kick out, bye
If LoginStatus = False Then
lblMsg.Text = "Login Error: Please check you user name and password"
Else
'good login and pass in a Session Variable "LoginStatus" to record if the user already login correctly
Response.Redirect("Search.aspx?LoginStatus=" & LoginStatus.ToString)
End If
End Sub

All I needed to do was to declare a public boolean for LoginStatus and add

 & "&LoginStatus=" & Page.Request("LoginStatus")

in the end of every redirect url code of all pages in the project.

I only then have to add this bit of code to every pages in the sub pageload

LoginStatus = Convert.ToBoolean(Page.Request("LoginStatus"))
If LoginStatus = False Then
Response.Redirect("Error.aspx")
End If

and so it redirect any unauthorised users trying to access a different page to the error.aspx page.

While I found this code to be working quite well, I didn't like the fact that the boolean value for the LoginStatus can be easily changed in the address of any browser. (usually it's LoginStatus = False if users haven't logged in, but anyone can change it to True via the address url when they trying to access different page) And also it hasn't really stored the CustomerID as a session variable.

So not much of a security and probably not the lecturer might want to see in a real ecommerce site.

Is there any method to combine your bit of code (session variable) with my friend's code (login feature). I believed his code for the login interface is better suited as my lecturer will be able to see that those codes were drawn and modified from other example codes he gave to us. (and I could understand better too)

All I'm missing right is the "unique CustomerID must be stored in a session variable for use in later module" part.

Also,

 FormsAuthentication.RedirectFromLoginPage(txtUserName.Text, True)

doesn't work as FormsAuthentication gave me an error that it was not declared.

Thanks a lot again for putting so much time in helping me, I really appreciated it. It certaintely has helped me a lot so far, especially in understanding how the codes work.
Okay, after messing with the code, I got it working once.

When it works, I cannot access any other pages beside index.aspx. And after logging in, I can continue to access other pages.

Unfortunately, I changed the code again (edit to remove my friend's code) and for some reasons, it didn't work again.

While the login interface works, I can now access other pages without logging in first.

I had this bit of code in the web.config file, which was never changed when it worked.


<authentication mode="Forms"
<forms loginUrl="index2.aspx" protection="All" /
</authentication
<authorization>
<deny users="?"/>
</authorization>

When I tried <deny users="*"/>, I was able to prevent access to any other pages beside index.aspx. However, even logging in would not let me to access other pages, which was expected.

So I really have no idea why it worked before and it doesn't work now.

This is the code in the index.aspx (login) page.


<script language="VB" runat="server"
Sub cmdLogin_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdLogin.Click

Dim xmldoc As New System.Xml.XmlDocument

xmldoc.Load(Server.MapPath("CustomerInfo.xml"))

Dim xmlnodelist As System.Xml.XmlNodeList

xmlnodelist = xmldoc.SelectNodes("/CustomerInfo/Customer[Username='" & txtUserName.Text & "']")

If xmlnodelist.Count > 1 Then

'error more than one of the same username found

'this should not happen

ElseIf xmlnodelist.Count = 0 Then

'username not found

lblMsg.Text = "Username not Found"

Else

Dim xmlel As System.Xml.XmlNode = xmlnodelist.Item(0)

Dim passNode As System.Xml.XmlNode = xmlel.SelectSingleNode("Password")

Dim custIDNode As System.Xml.XmlNode = xmlel.SelectSingleNode("CustomerID")

Dim custID As String = custIDNode.InnerText

Session("CustID") = custID

If passNode.InnerText = txtUserPass.Text Then

'login ok

'redirect to new page or whatever
lblMsg.Text = "Login successful!"

FormsAuthentication.RedirectFromLoginPage(txtUserName.Text, True)
Response.Redirect("Search.aspx")

Else

lblMsg.Text = "Invalid Password"

End If

End If

End Sub
</script>

I was sooo close to get it working, but I messed it up. :( Can someone please help me?
Why do you have response.redirect("search.aspx")? The FormsAuthentication.RedirectFromLoginPage(txtUserName.Text, True) is the code that redirects to the page the user is trying to get to.
I got it all working perfectly now. Thanks again for the code. :)

For the response.redirect("search.aspx"), the previous line of code only redirect me to a "default.aspx", which is not what I want. Thus I added in the redirect to search.aspx instead, which works when a user has successfully logged in.

Thanks for the help again. (hope none of my classmates find their way to this post. lol)

0 comments:

Post a Comment