Problems with cookies - error messages being produced

I have set up a logon to a site - using cookies.  Sometimes i get the following error:  

Error Type:
(0x80020009)
Exception occurred.
/familyregister/logon.asp, line 28

When i remove the cookies - the site works.  

Line 28:  rsLogin.Close()

Here is the code within the header:
<%
Function fLogin()
Dim rsLogin__cUsername
rsLogin__cUsername = "xyz"
If (Request.Cookies("LogonCookie")("Username") <> "") Then rsLogin__cUsername = Request.Cookies("LogonCookie")("Username")

Dim rsLogin__cPassword
rsLogin__cPassword = "xyz"
If (Request.Cookies("LogonCookie")("Password") <> "") Then rsLogin__cPassword = Request.Cookies("LogonCookie")("Password")

Dim rsLogin
Dim rsLogin_numRows

Set rsLogin = Server.CreateObject("ADODB.Recordset")
rsLogin.ActiveConnection = MM_conSWRMC_STRING
rsLogin.Source = "SELECT *  FROM tblMembers  WHERE Username='" + Replace(rsLogin__cUsername, "'", "''") + "' AND Password='" + Replace(rsLogin__cPassword, "'", "''") + "'"
rsLogin.CursorType = 0
rsLogin.CursorLocation = 2
rsLogin.LockType = 1
rsLogin.Open()
rsLogin_numRows = 0

If rsLogin("MemberID")<>"" Then fLogin=rsLogin("MemberID")
rsLogin.Close()
set rsLogin=Nothing
End Function
%>

<%
Sub sCreateCookies(cUsername, cPassword)
      Response.Cookies("LogonCookie")("Username")=cUsername
      Response.Cookies("LogonCookie")("Password")=cPassword
      Response.Cookies("LogonCookie").Expires=DateAdd("m",1,Now())
End Sub
%>

<%
If Request.Cookies("LogonCookie")("Username")<>""Then
      Dim vMemberID
      vMemberID=fLogin()
      If vMemberID<>"" Then
            Session("MemberID")=vMemberID
            Response.Cookies("LogonCookie").Expires=DateAdd("m",1,Now())
            Response.Redirect "loggedin.asp"
      End if
End if
%>

<%
' *** Validate request to log in to this site.
MM_LoginAction = Request.ServerVariables("URL")
If Request.QueryString<>"" Then MM_LoginAction = MM_LoginAction + "?" + Server.HTMLEncode(Request.QueryString)
MM_valUsername=CStr(Request.Form("username"))
If MM_valUsername <> "" Then
  MM_fldUserAuthorization=""
  MM_redirectLoginSuccess="loggedin.asp"
  MM_redirectLoginFailed="logon.asp"
  MM_flag="ADODB.Recordset"
  set MM_rsUser = Server.CreateObject(MM_flag)
  MM_rsUser.ActiveConnection = MM_conSWRMC_STRING
  MM_rsUser.Source = "SELECT MemberID, Username, Password"
  If MM_fldUserAuthorization <> "" Then MM_rsUser.Source = MM_rsUser.Source & "," & MM_fldUserAuthorization
  MM_rsUser.Source = MM_rsUser.Source & " FROM tblMembers WHERE Username='" & Replace(MM_valUsername,"'","''") &"' AND Password='" & Replace(Request.Form("password"),"'","''") & "'"
  MM_rsUser.CursorType = 0
  MM_rsUser.CursorLocation = 2
  MM_rsUser.LockType = 3
  MM_rsUser.Open
  If Not MM_rsUser.EOF Or Not MM_rsUser.BOF Then
    ' username and password match - this is a valid user
   
        'CREATE THE COOKIES
        Call sCreateCookies(MM_rsUser("Username"), MM_rsUser("Password"))
   
    Session("MM_Username") = MM_valUsername
            Session("MemberID") = MM_rsUser("MemberID")
    If (MM_fldUserAuthorization <> "") Then
      Session("MM_UserAuthorization") = CStr(MM_rsUser.Fields.Item(MM_fldUserAuthorization).Value)
    Else
      Session("MM_UserAuthorization") = ""
    End If
    if CStr(Request.QueryString("accessdenied")) <> "" And false Then
      MM_redirectLoginSuccess = Request.QueryString("accessdenied")
    End If
    MM_rsUser.Close
Response.Cookies("userloggedin") = "yes"
    Response.Redirect(MM_redirectLoginSuccess)
  End If
  MM_rsUser.Close
  Response.Redirect("logon.asp?err=1")
  End if
  %>

Here is the code on the loggedin page:

<%
If Request.QueryString("action")="logout" Then
Response.Cookies("userloggedin")=""
Response.Cookies("LogonCookie")("Username")=""
Response.Cookies("LogonCookie")("Password")=""
Response.Cookies("LogonCookie").Expires=Now()
Session.Abandon()
Response.Redirect("index.asp")
End if
%>

<%
Dim rsMember__loggedin
rsMember__loggedin = "0"
If (Session("MemberID") <> "") Then
  rsMember__loggedin = Session("MemberID")
End If
%>
<%
Dim rsMember
Dim rsMember_numRows

Set rsMember = Server.CreateObject("ADODB.Recordset")
rsMember.ActiveConnection = MM_conSWRMC_STRING
rsMember.Source = "SELECT * FROM tblMembers WHERE MemberID=" + Replace(rsMember__loggedin, "'", "''") + ""
rsMember.CursorType = 0
rsMember.CursorLocation = 2
rsMember.LockType = 1
rsMember.Open()

rsMember_numRows = 0
%>

I would be grateful for some assistance with this.

Kind regards


NorthDorsetWebAsked:
Who is Participating?
 
DropZoneCommented:
Ok, my code is posted below.  I have tested it and it works, but it will require you to change things on your end.  It makes certain assumptions, but they are reasonable.

Assumptions:
1. That there is a login page with username and password fields.
2. That any authentication errors will redirect to the login page with an ErrorCode in the QueryString, so that the login page can display an appropriate error message.
3. That the authentication functions will be available to all pages (like in a server-side include).
4. That every page that requires authentication will use the session validation function.
5. That you do not have any encryption mechanisms available, so we are just simply setting the userid in the Session State as the auth token.  Of course, eventually you should work on getting some decent encryption here.
6. That you have a valid connection string in a variable called MM_conSWRMC_STRING
7. That your login query is "SELECT *  FROM tblMembers  WHERE Username=? AND Password=?"

The ErrorCodes are:
ERR_INVALID  : Invalid username or password
ERR_DBCMD   : An error occurred executing the database statement
ERR_DBCONN : An error occurred connecting to the database
ERR_LOGOUT : The user has been logged out (auth session destroyed)
ERR_SESSION : An invalid or missing session has been detected, the user must login.

The authentication mechanism works like this:
1. When any page other than the login page is requested, the function AuthenticateSession() is called at the top.  If session authentication failed, the user is redirected to the login page with ERR_SESSION.
2. When the login page is requested the first time, the login prompt with be displayed.
3. When the user submits the login page, the LoginUser() function is called.  If authentication failes the return value of the function will be the ErrorCode which then can be displayed to the user.  If authentication succeeds (the ErrorCode is "") then you should redirect to your main page and the cycle continues.

**** AUTH FUNCTIONS ****
You should put this on a separate module file and import it into all your secure pages using a server-side include. Make sure that you initialize the connection string variable (MM_conSWRMC_STRING) and that it is accessible to this file.  I will call this file "auth_lib.asp" in my code below.

FILE: auth_lib.asp
<%
      ' This points to your login page.  It will be used in automatic redirections
      Const C_LOGIN_PAGE_URL = "/login.asp"

' --------------------------------------
' -- Login User
' --------------------------------------
Function LoginUser
      Dim objConn
      Dim objCmd
      Dim objRecSet
      Dim objParam
      Dim objErr
      Dim strUsername
      Dim strPassword
      Dim strMemberID
      Dim strError

      ' Default to failure
      strError     = "ERR_INVALID"
      strUsername  = Request.Form("username")
      strPassword  = Request.Form("password")

      ' If for some reason this user is logged in, close the session
      Session.Contents.RemoveAll()

      If (strUsername = "") OR (strPassword = "") Then Exit Function

      ' Ignore errors when they happen so that we can detect them manually
      On Error Resume Next

      ' Initialize the Connection and Command objects
      '
      ' Use a command object instead of a RecordSet object.
      ' The command object will return a recordset.
      Set objConn = Server.CreateObject("ADODB.Connection")
      Set objCmd  = Server.CreateObject("ADODB.Command"   )

      ' Initialize the connection
      '   -----
      '   NOTE:  I assume MM_conSWRMC_STRING is a valid connection string
      '   -----
            objConn.CursorLocation    = adUseServer
            objConn.ConnectionString  = MM_conSWRMC_STRING
            objConn.ConnectionTimeout = 30
            objConn.CommandTimeout    = 30
            objConn.Open MM_conSWRMC_STRING

      ' Continue if the connection is active
      If (objConn.State <> adStateClosed) Then
            ' Initialize the command
                  objCmd.ActiveConnection = objConn
                  objCmd.CommandText      = "SELECT *  FROM tblMembers  WHERE Username=? AND Password=?"

            ' Initialize the parameters
            ' Username
            Set objParam = objCmd.CreateParameter("Username")
                  objParam.Type      = adVarChar
                  objParam.Value     = strUsername
                  objParam.Direction = adParamInput
                  objParam.Size      = Len(strUsername)
            objCmd.Parameters.Append objParam

            ' Password
            Set objParam = objCmd.CreateParameter("Password")
                  objParam.Type      = adVarChar
                  objParam.Value     = strPassword
                  objParam.Direction = adParamInput
                  objParam.Size      = Len(strPassword)
            objCmd.Parameters.Append objParam

            Set objParam = Nothing

            ' Execute the query and get the record set
            objCmd.Prepared = True
            Set objRecSet = objCmd.Execute( , , adCmdText)

            ' Check to see if there were any errors
            If (Err.Number <> 0) OR (objConn.Errors.Count > 0) Then
               ' and error occurred! handle it!
               ' you may want to loop through the Errors
               ' collection to discover them

                  strError = "ERR_DBCMD"
            ElseIf NOT (objRecSet.BOF AND objRecSet.EOF) Then
                  strMemberID = objRecSet("MemberID")

                  If (strMemberID <> "") Then
                        ' We found the user!
                        strError = ""

                        ' Initialize the Authorized Session.
                        ' You may want to store other user information here
                        Session("AUTH_USER") = strMemberID

                        ' Preferrably, you would store an encrypted token
                        ' which would then be also sent as a cookie and
                        ' then validated on each request.
                  End if
            End If

            objRecSet.Close()
            objConn.Close()
      Else
            ' You may want to log these errors.

            strError = "ERR_DBCONN"
      End If

      set objRecSet = Nothing
      set objCmd    = Nothing
      set objConn   = Nothing

      ' Disable ignore errors
      On Error Goto 0

      LoginUser = strError
End Function

' --------------------------------------
' -- Logout User
' --------------------------------------
Sub LogoutUser
      ' If you set an Auth Cookie, you should delete it here

      ' Clear the session
      Session.Abandon()
      RedirToLogin "ERR_LOGOUT"
End Sub

' --------------------------------------
' -- Redirect to Login Screen
' --------------------------------------
Sub RedirToLogin(ByVal strErrCode)
      Response.Redirect(C_LOGIN_PAGE_URL & "?error=" & strErrCode)
End Sub

' --------------------------------------
' -- Authenticate Session
' --------------------------------------
Sub AuthenticateSession
      Dim strAuthUser

      strAuthUser = Session("AUTH_USER")

      ' If you set an Auth Cookie you should decrypt it and
      ' validate it here against the token stored in the session.

      If (strAuthUser = "") Then
            Session.Abandon()
            RedirToLogin "ERR_SESSION"
      End If
End Sub
%>
************* END OF FILE

**** LOGIN PAGE ****
This is a sample of what to include in your login page to use this authentication model.  Notice that I use a server-side include to import the auth_lib.asp file.  You should set the virtual path to point to where you located the file.

FILE: login.asp
<%
      Option Explicit
%>
<!-- #include virtual="auth_lib.asp" -->
<%
Dim ERROR_CODE : ERROR_CODE = ""

      ' Check if the login form was submitted (i.e. the button was clicked)
      If Request.Form("btnLogin") <> "" Then
            ERROR_CODE = LoginUser()

            ' Login succeeded, redirect to main page!
            If ERROR_CODE = "" Then
                  Response.Redirect("/main.asp")
            End If
      Else
            ' Get the error code from the query string (if any)
            ERROR_CODE = Request.QueryString("error")
      End If

%>
<html>
<body>
<%
      If ERROR_CODE <> "" Then
            ' Of course, you may want to display user-friendly errors
            Response.write "<p>Error: " & ERROR_CODE & "</p>"
      End If
%>
      <form action="/t_login.asp" method="POST">
            <input type="text" name="username" value=""><br>
            <input type="text" name="password" value=""><br>
            <input type="submit" name="btnLogin" value="Login">
      </form>
</body>
</html>
************* END OF FILE

**** MAIN AND OTHER PAGES ****
This is an example of how to use this authentication model in all your other pages.  Below is an example page called "main.asp".  Notice it also includes auth_lib.asp and that the first thing it does is to authenticate the session.

FILE: main.asp
<%
      Option Explicit
%>
<!-- #include virtual="auth_lib.asp" -->
<%
      ' Authenticate our session.  If it failed, it will
      ' redirect automatically to the login page.
      ' Otherwise it continues as if nothing happened.
      Call AuthenticateSession()
%>
<html>
<body>
      <p>
      You're in main 1!
      </p>
</body>
</html>
************* END OF FILE


I have commented the code as best as I could and I put some recommendations in there also.  Let me know if you have any questions or problems.

     Cheers!
      -dZ.
0
 
DropZoneCommented:
Check this page for help on this issue:
http://classicasp.aspfaq.com/general/why-do-i-get-80020009-errors.html

     -dZ.
0
 
CWS (haripriya)Commented:
Try this:

If rsLogin.state = 1 then rsLogin.Close()
0
Cloud Class® Course: MCSA MCSE Windows Server 2012

This course teaches how to install and configure Windows Server 2012 R2.  It is the first step on your path to becoming a Microsoft Certified Solutions Expert (MCSE).

 
DropZoneCommented:
My guess is that the connection is not opened when you try to close it, possibly because the query failed.  First thing you should try is to output the query after you put the cookie values to see what you are actually sending to the server.  You should also use Parametized Queries, instead of using the Cookie values directly -- as it stands, you are open to a vary nasty SQL Injection attack.

Also, you may want to trap errors by wrapping the code within a Try...Catch block.  Hopefully you'll be able to find out what the exact problem is then.

     -dZ.
0
 
effxCommented:
Replace :
       Call sCreateCookies(MM_rsUser("Username"), MM_rsUser("Password"))
With
       sCreateCookies Replace(MM_valUsername,"'","''"), Replace(Request.Form("password"),"'","''")
0
 
NorthDorsetWebAuthor Commented:
HI DropZone - im sorry im not that experienced, im happy to try what you have suggested but i will need help trying to achieve what you are asking me to do.

Cyber and effx - Ill be tryign twhat you suggested - can you please let me know what the changes will do - just im never going to learn anything!

Kind regards
Emma
0
 
DropZoneCommented:
' This will only attempt to close the connection if it is actually opened
'  State = 1 means "Connected.
If rsLogin.state = 1 then rsLogin.Close()

' This will replace single-quotes with doubled single-quotes
sCreateCookies Replace(MM_valUsername,"'","''"), Replace(Request.Form("password"),"'","''")

About that second line, why are you expecting single quotes to be included within the username and password strings?  If you are trying to prevent SQL Injection, just use parametized queries.  Try the following:

Dim cmdLogin
Dim rsLogin
Dim rsLogin_numRows
Dim ParamObj

' Ignore errors when they happen so that we can detect them manually
On Error Resume Next

' Use a command object instead of a RecordSet object.
' The command object will return a recordset.
Set cmdLogin = Server.CreateObject("ADODB.Command")

' I assume MM_conSWRMC_STRING is a valid connection object
cmdLogin.ActiveConnection = MM_conSWRMC_STRING
cmdLogin.CommandText = "SELECT *  FROM tblMembers  WHERE Username=? AND Password=?"

' add parameters:
' Username
Set ParamObj = cmdLogin.CreateParameter('Username')
    ParamObj.Type = adVarChar
    ParamObj.Value = rsLogin__cUsername
    ParamObj.Direction = adParamInput
    ParamObj.Size = Len(rsLogin__cUsername)
cmdLogin.Parameters.Append objParam

' Password
Set ParamObj = cmdLogin.CreateParameter('Username')
    ParamObj.Type = adVarChar
    ParamObj.Value = rsLogin__cPassword
    ParamObj.Direction = adParamInput
    ParamObj.Size = Len(rsLogin__cPassword)
cmdLogin.Parameters.Append objParam

Set ParamObj = Nothing

' Execute the query and get the record set
Set rsLogin = cmdLogin.Execute( , , adCmdText)

rsLogin_numRows = 0

' Check to see if there were any errors
If (Err.Number <> 0) OR (MM_conSWRMC_STRING.Errors.Count > 0) Then
   ' and error occurred! handle it!
   ' you may want to loop through the Errors collection to discover them
ElseIf NOT(rsLogin.BOF AND rsLogin.EOF) Then
    ' we found the user
    If rsLogin("MemberID")<>"" Then fLogin=rsLogin("MemberID")
Else
    fLogin = ""
End If

rsLogin.Close()
set rsLogin=Nothing
set cmdLogin = Nothing


' disable ignore errors
On Error Goto 0


   -dZ.
0
 
effxCommented:
Ok on mine instead of getting the data from the database, the cookies will be set from the input from the user, which is the normal way that cookies would be set in authentication type processes.
0
 
DropZoneCommented:
First, the code that I provided is only for the authentication with the database, it assumes that the rsLogin__cUsername and rsLogin__cPassword variables have been already set.  Notice how I didn't specify that it was the entire fLogin function, just the part that connects to the DB.

My code was to solve your database issue, that's all it does: it replaces only the part on your code that accesses the database.  I didn't even try to improve on your cookie usage, even though I think it should be done differently, but that's another issue.  You were having a database issue.

Second, you *NEVER* want to store the username and password in the cookies.  *NEVER*.  Not even if encrypted.  That's a very  nasty security vulnerability right there (apart from the SQL injection vulnerability you currently had without parametized queries).

If you want to do it "the normal way that cookies would be set in authentication type processes", then what you really want to do is to generate  an authentication token: a unique string (perhaps composed of a hash from the username/timestamp, or maybe even a new GUID generated by the database), and store that in the cookie.  Then on every request, you check that the token is valid (by comparing it to a local copy, say, in the Session() state mapped to that user).  But, like I said, that's another issue.

Let me know if the database code fixed your problem.
    Cheers!
      -dZ.
0
 
effxCommented:
This is true about the security implications, however to answer the question that was asked would be the solution i provided.

I would encrypt using the session cookies, but thats not question that question was why is it not working, and once again it was the way the cookies were handled.
0
 
effxCommented:
However there are many sites that store passwords in cookies when the user selects remember me for example hotmail, the only security implication that would be a problem is that if you had a public computer accessing your site however using the cookies method will overwrite the username cookie everytime a user logs in, so it will only store the last cookie along with the password.
0
 
DropZoneCommented:
effx: Actually, if you want to get pedantic and technical, the question was help with the error and the error was at closing the recordset.  The correct fix for that error was provided by cyberwebservice.

But we can all agree that doing that will not make the site work, so we are all trying to provide helpful assistance to ensure that the overal solution corrects this.  I for one am not shopping for points; I just want to help.  And if I can aide in preventing another site from becomming yet another zombie-laden cracker haven on the Internet, then better still.

About storing the password in the cookie:  This was a technique used during the 90s and early 2000s, before the onset of practical web application security came to the mainstream.  The fact that many sites still use it is in itself not a reason why you should also follow an unsecure and deprecated practice.  The way to properly do the "remember me" option is to set the auth cookie as a "persistent" cookie (as opposed to "session" cookie), which will store it in the cookies file of the browser, with an expiration date of long into the future.  Again, this cookie should contain an authentication token, not login information.  It is inconvenient to keep track of persistent sessions, as the default is to expire them, but storing the login information in the cookie is just that: convenient, not secure.  I wouldn't recommend it, neither would security experts, but of course, if you value convenience and quick programming solutions over security and integrity then that would be the way to go.  I pressumed that NorthDorsetWeb did not.

     -dZ.
0
 
NorthDorsetWebAuthor Commented:
Hi there
Thank you for your responses.  Im sorry if I have started a debate!  
Im trying to find the best solution that I can set up myself and which I can understand.  DropZone is there someway that I can set up the solution you suggest?  I will need pointing to a good tutorial if thats the case because I am still learning and having to use the best resources I can - of course i only know what i can find.
also your sugestion to remove the error - albeit not entirely secure as i now undertsand it is:
If rsLogin.state = 1 then rsLogin.Close()

Does that replace the rsLogin.close() line below or do I have to do something to the line above as follows:
If rsLogin("MemberID")<>"" Then fLogin=rsLogin("MemberID")
rsLogin.Close()

I really appreciate your help with this and I apologise if I appear to be dumb!
Emma

0
 
NorthDorsetWebAuthor Commented:
Can I simply use the code you have provided to replace my existing code and if so, which parts should I be replacing?
0
 
DropZoneCommented:
>> DropZone is there someway that I can set up the solution you suggest?

Check out these guys, they offer very good tutorials on Classic ASP and ASP.NET.  In particular, check the the section entitled "Creating a Database-Driven Login Page".
http://www.4guysfromrolla.com/webtech/LearnMore/Authentication.asp

>> If rsLogin.state = 1 then rsLogin.Close()

That will close the connection only if it is opened.  However, if the connection is not opened by then something else wrong happened, but with your code you can't tell.

>> If rsLogin("MemberID")<>"" Then fLogin=rsLogin("MemberID")
>> rsLogin.Close()

That is not necessary.  All you need to do is check if the connection was established and if there are records returned.  If there are no records returned, then accessing the recordset will fail, which could be your underlying problem.  The code I presented deals with this.

>> I really appreciate your help with this and I apologise if I appear to be dumb!

Its my pleasure, and you do not appear dumb at all.  We are all inexperienced at things new to us, and even the experts had to learn somehow at some point.

You should be able to use the code I posted, which detects the errors.  It should replace the part in the fLogin() function that accesses the database. However, I still suggest you change your cookies usage to store a Session ID generated instead of the username and password, or use the Session State (as the tutorials explain) to store the authentication information.

I'm afraid I cannot give you full code for this solution, as I have none at hand, but at least you should understand the basic concept:

1. Receive the Username and Password values from the Login form.
2. Authenticate them against the database.
3. If failed, re-desplay the Login form with an error message (make it generic! you do not want to specify whether the username or the password fail, just that the authentication failed.)
4. If succeeded, generate an authentication token and store this in the Session state.
5. On every postback, at the beginning of each ASP page that should be protected, before doing anything else, validate the authentication token.  This could be a matter of checking if it is set (for example, you can store the username there; if there is no username when you check, then the session is invalid!).
6. If validation failed, redirect the user to the Login screen again with an error message.
7. If succeeded, continue as normal.

    That's it.  For security purposes you may want to encrypt the token or tack a random string onto it to guarantee it is unique.  You may also want to generate a new "authorization" cookie with the encrypted token, that way you only validate those who have such cookie, and anybody else is immediately sent to the login screen with a "You must log in" message or something like it.

    The idea is first, to not send the authentication credentials back and forth between the server and browser constantly (which is insecure), and second, to authenticate with the database once and use a secret and unique token to validate authorization on every request.

     I hope this helps.
     -dZ.
0
 
NorthDorsetWebAuthor Commented:
What ive decided to do is get this working - if i can - and then work on setting up a more secure page using your suggested solution.

The problem is i have tried the two suggestions: the first rslogin.close etc.... does nothing although it does allow a logged out user to access every page.

the second solution produces an error saying expected end.

Any ideas?

Kind regards
emma
0
 
DropZoneCommented:
Can you post your revised code?

   -dZ.
0
 
effxCommented:
NorthDorsetWeb you have dealt with me once before, I made a suggestion last time we talked about the login page and scripts that go with it, if you still wish to get this site up and running sooner rather than later you should still have my email address.
0
 
NorthDorsetWebAuthor Commented:
Here is the code for the first solution:

<%
Function fLogin()
Dim rsLogin__cUsername
rsLogin__cUsername = "xyz"
If (Request.Cookies("LogonCookie")("Username") <> "") Then rsLogin__cUsername = Request.Cookies("LogonCookie")("Username")

Dim rsLogin__cPassword
rsLogin__cPassword = "xyz"
If (Request.Cookies("LogonCookie")("Password") <> "") Then rsLogin__cPassword = Request.Cookies("LogonCookie")("Password")

Dim rsLogin
Dim rsLogin_numRows

Set rsLogin = Server.CreateObject("ADODB.Recordset")
rsLogin.ActiveConnection = MM_conSWRMC_STRING
rsLogin.Source = "SELECT *  FROM tblMembers  WHERE Username='" + Replace(rsLogin__cUsername, "'", "''") + "' AND Password='" + Replace(rsLogin__cPassword, "'", "''") + "'"
rsLogin.CursorType = 0
rsLogin.CursorLocation = 2
rsLogin.LockType = 1
rsLogin.Open()
rsLogin_numRows = 0

If rsLogin.state = 1 then rsLogin.Close()
set rsLogin=Nothing
End Function
%>

This appears to do nothing but allows all pages to be viewed - there are a nmber o pages I have restricted to those logged in and here is the code on those pages

<%If Request.Cookies("userloggedin") <> "yes" Then Response.Redirect "/logon.asp"%>

I shall post the other solution separately.
0
 
NorthDorsetWebAuthor Commented:
Effx thanks for your help - have you any idea how much this solution would be - as i mentioned before we dont have much of a budget for outside solutions
0
 
NorthDorsetWebAuthor Commented:
I changed the above amendments back -not sure if I should have done this and then added the other solution as suggested:  here is the code:

<%
' *** Validate request to log in to this site.
MM_LoginAction = Request.ServerVariables("URL")
If Request.QueryString<>"" Then MM_LoginAction = MM_LoginAction + "?" + Server.HTMLEncode(Request.QueryString)
MM_valUsername=CStr(Request.Form("username"))
If MM_valUsername <> "" Then
  MM_fldUserAuthorization=""
  MM_redirectLoginSuccess="loggedin.asp"
  MM_redirectLoginFailed="login.asp"
  MM_flag="ADODB.Recordset"
  set MM_rsUser = Server.CreateObject(MM_flag)
  MM_rsUser.ActiveConnection = MM_conSWRMC_STRING
  MM_rsUser.Source = "SELECT MemberID, Username, Password"
  If MM_fldUserAuthorization <> "" Then MM_rsUser.Source = MM_rsUser.Source & "," & MM_fldUserAuthorization
  MM_rsUser.Source = MM_rsUser.Source & " FROM tblMembers WHERE Username='" & Replace(MM_valUsername,"'","''") &"' AND Password='" & Replace(Request.Form("password"),"'","''") & "'"
  MM_rsUser.CursorType = 0
  MM_rsUser.CursorLocation = 2
  MM_rsUser.LockType = 3
  MM_rsUser.Open
  If Not MM_rsUser.EOF Or Not MM_rsUser.BOF Then
    ' username and password match - this is a valid user
   
        'CREATE THE COOKIES
       sCreateCookies Replace(MM_valUsername,"'","''"), Replace(Request.Form("password"),"'","''")
   
    Session("MM_Username") = MM_valUsername
            Session("MemberID") = MM_rsUser("MemberID")
    If (MM_fldUserAuthorization <> "") Then
      Session("MM_UserAuthorization") = CStr(MM_rsUser.Fields.Item(MM_fldUserAuthorization).Value)
    Else
      Session("MM_UserAuthorization") = ""
    End If
    if CStr(Request.QueryString("accessdenied")) <> "" And false Then
      MM_redirectLoginSuccess = Request.QueryString("accessdenied")
    End If
    MM_rsUser.Close
Response.Cookies("userloggedin") = "yes"
    Response.Redirect(MM_redirectLoginSuccess)
  End If
  MM_rsUser.Close
  Response.Redirect("logon.asp?err=1")
  End if
  %>

Basically if i can get this working so the error is produced then i can then concentrate on getting a more efficient solution.


Kind regards
emma
0
 
DropZoneCommented:
NorthDorsetWeb, there is no need to pay money for this:  I'm sure we can work it out for free in this forum.  I'm not even doing this for the points.

Once we get this working, you can post a new question some other day to improve the algorithm and the security.

I'll post some working code for you shortly.

    -dZ.

0
 
NorthDorsetWebAuthor Commented:
Ok thank you so much.
0
 
effxCommented:
I am not offering my services for money, I am just here to help.
0
 
effxCommented:
<%
'Call it something like login.asp
'This file to allow logins
Database_Path = MM_conSWRMC_STRING 'I would rather use something else.
'Database_Path = Server.MapPath("/") & "\..\database\" & "effxdesign.mdb"
Bad_Login = "login.asp" ' I would use the next line instead, to use it just un-comment
'Bad_Login = Request.ServerVariables("PATH_INFO") ' If this line in uncommented then uncomment the next aswell
'Pass_Errors = True
Good_Login = "loggedin.asp" ' This is where the user gets redirected if the login is successful
Site_Name = "NDW" ' No spaces in here
Function DeHack (String_To_Parse) ' This function will prevent SQL Injection (Security Fix)
      Output_String = Replace(String_To_Parse, "'", "")
      Output_String = Replace(Output_String, "%", "")
      DeHack = Output_String
End Function
Sub Process_Login (string_username, string_password)
      Set FAQListingsConnection = Server.CreateObject("ADODB.Connection")
      FAQListingsConnection.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & Database_Path & ";Persist Security Info=False"
      sSQL = "SELECT MemberID, Username, Password FROM tblMembers WHERE Username = '" & string_username & "'"
      sSQL = "SELECT * FROM members WHERE Username = '" & string_username & "'"
      Set FAQListingsRecord = FAQListingsConnection.Execute(sSQL)
            If FAQListingsRecord.BOF Or FAQListingsRecord.EOF Then
                  Login_Error = 1
            Else
                  If FAQListingsRecord("password") <> string_password Then
                        Login_Error = 2
                  Else
                        Login_Error = 3
                  End If
            End If
                  FAQListingsConnection.Close
            Set FAQListingsRecord = Nothing
      Set FAQListingsConnection = Nothing
      Select Case Login_Error
            Case 1 ' Not a user
                  Go_Page = Bad_Login
            Case 2 ' Password is wrong
                  Go_Page = Bad_Login
            Case 3 ' Login information is correct
                  Session(Site_Name)("username") = string_username
                  Session(Site_Name)("password") = string_password
                  Go_Page = Good_Login
            Case Else ' No Error specified
                  Go_Page = Bad_Login
      End Select
      If Pass_Errors = True Then
            Response.Redirect(Go_Page & "?er=" & Login_Error)
      Else
            Response.Redirect(Go_Page)
      End If
End Sub
Sub Add_Cookie (which_one, add_value)
      Response.Cookies(Site_Name)(which_one) = add_value
End Sub
If Request.Form <> "" Then
      username = DeHack(Request.Form("username"))
      password = DeHack(Request.Form("password"))
      Response.Cookies(Site_Name)("save_login") = Request.Form("save_login")
      Select Case Int(Request.Form("save_login"))
            Case 1
                  Response.Cookies(Site_Name)("username") = username
            Case 2
                  Response.Cookies(Site_Name)("username") = username
                  Response.Cookies(Site_Name)("password") = password
            Case Else
                  Response.Cookies(Site_Name) = ""
      End Select
      Process_Login username, password
End If
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Login Screen</title>
</head>

<body>
<%If Request.QueryString("er") <> "" Then
Select Case Int(Request.QueryString("er"))
      Case 1
            Message_Output = "Sorry you are not a user."
      Case 2
            Message_Output = "Sorry your password is incorrect."
      Case Else
            Message_Output = "Un specified error."
End Select
%>
<script language="javascript" type="text/javascript">
alert('<%=Message_Output%>');
</script>
<%End If%>
<form method="post" action="<%= Request.ServerVariables("PATH_INFO")%>">
  <table>
    <tr><td>Username</td><td>:</td><td><input type="text" name="username" value="<%= Request.Cookies(Site_Name)("username")%>"></td></tr>
    <tr><td>Password</td><td>:</td><td><input type="password" name="password" value="<%= Request.Cookies(Site_Name)("password")%>"></td></tr>
    <tr><td colspan="3">
        <input type="radio" name="save_login" value="0" id="save_login_0"<%If Int(Request.Cookies(Site_Name)("save_login")) = 0 Then%> checked="checked"<%End If%>><label for="save_login_0">Do not remember me</label><br>
        <input type="radio" name="save_login" value="1" id="save_login_1"<%If Int(Request.Cookies(Site_Name)("save_login")) = 1 Then%> checked="checked"<%End If%>><label for="save_login_1">Remember username</label><br>
        <input type="radio" name="save_login" value="2" id="save_login_2"<%If Int(Request.Cookies(Site_Name)("save_login")) = 2 Then%> checked="checked"<%End If%>><label for="save_login_2">Remember username/pasword</label><br>
      </td></tr>
    <tr><td>&nbsp;</td><td>&nbsp;</td><td><input type="submit" value="Login"></td></tr>
  </table>
</form>
</body>
</html>
0
 
effxCommented:
Sorry my mistake :

<%
'Call it something like login.asp
'This file to allow logins
Database_Path = MM_conSWRMC_STRING 'I would rather use something else.
Bad_Login = "login.asp" ' I would use the next line instead, to use it just un-comment
'Bad_Login = Request.ServerVariables("PATH_INFO") ' If this line in uncommented then uncomment the next aswell
'Pass_Errors = True
Good_Login = "loggedin.asp" ' This is where the user gets redirected if the login is successful
Site_Name = "NDW" ' No spaces in here
Function DeHack (String_To_Parse) ' This function will prevent SQL Injection (Security Fix)
      Output_String = Replace(String_To_Parse, "'", "")
      Output_String = Replace(Output_String, "%", "")
      DeHack = Output_String
End Function
Sub Process_Login (string_username, string_password)
      Set FAQListingsConnection = Server.CreateObject("ADODB.Connection")
      FAQListingsConnection.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & Database_Path & ";Persist Security Info=False"
      sSQL = "SELECT MemberID, Username, Password FROM tblMembers WHERE Username = '" & string_username & "'"
      Set FAQListingsRecord = FAQListingsConnection.Execute(sSQL)
            If FAQListingsRecord.BOF Or FAQListingsRecord.EOF Then
                  Login_Error = 1
            Else
                  If FAQListingsRecord("password") <> string_password Then
                        Login_Error = 2
                  Else
                        Login_Error = 3
                  End If
            End If
                  FAQListingsConnection.Close
            Set FAQListingsRecord = Nothing
      Set FAQListingsConnection = Nothing
      Select Case Login_Error
            Case 1 ' Not a user
                  Go_Page = Bad_Login
            Case 2 ' Password is wrong
                  Go_Page = Bad_Login
            Case 3 ' Login information is correct
                  Session(Site_Name)("username") = string_username
                  Session(Site_Name)("password") = string_password
                  Go_Page = Good_Login
            Case Else ' No Error specified
                  Go_Page = Bad_Login
      End Select
      If Pass_Errors = True Then
            Response.Redirect(Go_Page & "?er=" & Login_Error)
      Else
            Response.Redirect(Go_Page)
      End If
End Sub
Sub Add_Cookie (which_one, add_value)
      Response.Cookies(Site_Name)(which_one) = add_value
End Sub
If Request.Form <> "" Then
      username = DeHack(Request.Form("username"))
      password = DeHack(Request.Form("password"))
      Response.Cookies(Site_Name)("save_login") = Request.Form("save_login")
      Select Case Int(Request.Form("save_login"))
            Case 1
                  Response.Cookies(Site_Name)("username") = username
            Case 2
                  Response.Cookies(Site_Name)("username") = username
                  Response.Cookies(Site_Name)("password") = password
            Case Else
                  Response.Cookies(Site_Name) = ""
      End Select
      Process_Login username, password
End If
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Login Screen</title>
</head>

<body>
<%If Request.QueryString("er") <> "" Then
Select Case Int(Request.QueryString("er"))
      Case 1
            Message_Output = "Sorry you are not a user."
      Case 2
            Message_Output = "Sorry your password is incorrect."
      Case Else
            Message_Output = "Un specified error."
End Select
%>
<script language="javascript" type="text/javascript">
alert('<%=Message_Output%>');
</script>
<%End If%>
<form method="post" action="<%= Request.ServerVariables("PATH_INFO")%>">
  <table>
    <tr><td>Username</td><td>:</td><td><input type="text" name="username" value="<%= Request.Cookies(Site_Name)("username")%>"></td></tr>
    <tr><td>Password</td><td>:</td><td><input type="password" name="password" value="<%= Request.Cookies(Site_Name)("password")%>"></td></tr>
    <tr><td colspan="3">
        <input type="radio" name="save_login" value="0" id="save_login_0"<%If Int(Request.Cookies(Site_Name)("save_login")) = 0 Then%> checked="checked"<%End If%>><label for="save_login_0">Do not remember me</label><br>
        <input type="radio" name="save_login" value="1" id="save_login_1"<%If Int(Request.Cookies(Site_Name)("save_login")) = 1 Then%> checked="checked"<%End If%>><label for="save_login_1">Remember username</label><br>
        <input type="radio" name="save_login" value="2" id="save_login_2"<%If Int(Request.Cookies(Site_Name)("save_login")) = 2 Then%> checked="checked"<%End If%>><label for="save_login_2">Remember username/pasword</label><br>
      </td></tr>
    <tr><td>&nbsp;</td><td>&nbsp;</td><td><input type="submit" value="Login"></td></tr>
  </table>
</form>
</body>
</html>
0
 
effxCommented:
This code will log people in however i would add another few lines in here to make it more secure but if you want we can discuss it more via email if you still have me email address, and im not in it for the money or the points just to make you aware.
0
 
NorthDorsetWebAuthor Commented:
Hi there, sorry for taking so long to get back to you on this - i have been on holiday.

Where you say I haev to make changes at my end - do you just mean to the current structure of pages, and the additional files as you have stated above?  
0
 
DropZoneCommented:
Yes, that's what I meant.  The changes you have to make are to add the above files, to remove the old authentication code, to modify the Login page as mentioned, and to add the Server-Side-Include and function call to authenticate on all pages you want to protect, as instructed in my past message.

Basically, the auth_lib.asp will become the centralized point for the authentication mechanism and all pages that require protection will need to include it.

If you save all three files in your webserver, you can test them and use them as an example of how to do this.

Let me know if you need help integrating any of it.

     -dZ.
0
 
NorthDorsetWebAuthor Commented:
Ok i have started to apply the information you sent to me to a test site.    What I have done to start with is set up a page (no headers or anything else) and called it auth_lib.asp.  Im assuming this is rather like a javascript script or CSS file that just contains the functions and nothing else.  Is this correct?

So far I have only looked at these two pages.  Here is my code for the logon page:

<%
      Option Explicit
%>
<%@LANGUAGE="VBSCRIPT" CODEPAGE="1252"%>
<!--#include file="Connections/conHospital.asp" -->
' Set your LCID here. For instance, '1033' is US-English regional setttings (default)
<% Session.LCID = 2057 'English regional setttings %>

<!-- #include virtual="securitytest/auth_lib.asp" -->
<%
Dim ERROR_CODE : ERROR_CODE = ""

      ' Check if the login form was submitted (i.e. the button was clicked)
      If Request.Form("btnLogin") <> "" Then
            ERROR_CODE = LoginUser()

            ' Login succeeded, redirect to main page!
            If ERROR_CODE = "" Then
                  Response.Redirect("/main.asp")
            End If
      Else
            ' Get the error code from the query string (if any)
            ERROR_CODE = Request.QueryString("error")
      End If

%>


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><!-- InstanceBegin template="/Templates/template.dwt" codeOutsideHTMLIsLocked="false" -->
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<!-- InstanceBeginEditable name="doctitle" -->
<title>IT Department Fault Reporting</title>
<!-- InstanceEndEditable --><!-- InstanceBeginEditable name="head" -->
<link href="style.css" rel="stylesheet" type="text/css">
<!-- InstanceEndEditable -->
<link href="/../style.css" rel="stylesheet" type="text/css">
<SCRIPT TYPE="text/javascript">
<!--
function popup(mylink, windowname)
{
if (! window.focus)return true;
var href;
if (typeof(mylink) == 'string')
   href=mylink;
else
   href=mylink.href;
window.open(href, windowname,'width=700,height=750,scrollbars=yes');
return false;
}
//-->
</SCRIPT>

<style type="text/css">
<!--
a:hover {
      color: #993333;
}
.style1 {color: #000000}
-->
</style>
</head>

<body onload="initPage()">
<div align="center">
  <table width ="700" border="0" cellpadding="0" cellspacing="0" id="maintable">
   
   
    <tr bordercolor="#FFFFCC">
      <td><div align="center"><img src="images/banner2.jpg" alt="Dorset PCT" width="692" height="93"></div></td>
    </tr>
    <tr align="left" valign="middle" bgcolor="#6633FF" id="menubar">
      <td bgcolor="#6666FF" id="menubar"><h2 align="center">IT Department Fault Reporting</h2>
      </td>
    </tr>
    <tr>
      <td><div align="center"><!-- InstanceBeginEditable name="EditRegion5" -->
        <p>&nbsp;</p>
        <!-- InstanceEndEditable --></div></td>
    </tr>
    <tr>
      <td>
        <!-- InstanceBeginEditable name="Content" -->
        <%
      If ERROR_CODE <> "" Then
            ' Of course, you may want to display user-friendly errors
            Response.write "<p>Error: " & ERROR_CODE & "</p>"
      End If
%>
      <form action="/t_login.asp" method="POST">
            <table width="500" border="0" cellspacing="0" cellpadding="4">
              <tr>
                <td><strong>Login</strong>:</td>
                <td><input type="text" name="username" value=""></td>
              </tr>
              <tr>
                <td><strong>Password</strong>:</td>
                <td><input type="text" name="password" value=""></td>
              </tr>
              <tr>
                <td>&nbsp;</td>
                <td><input type="submit" name="btnLogin" value="Login"></td>
              </tr>
            </table>
      </form>
        <!-- InstanceEndEditable --></td>
    </tr>
    <tr>
      <td><h6 align="center"><strong>Dorset Primary Care Trust : IT Department </strong></h6></td>
    </tr>
  </table>
</div>
</body>
<!-- InstanceEnd --></html>

I was getting an error on line 7 and so moved the option explicit to the top of the page, this is not producing the same error now.   Not sure if this was the right thing to do but Im now getting a new errorr:

The @ command must be the first command within the Active Server Page.
/securitytest/logon.asp, line 4

Thanking you in advance.
Kind regards
Emma

0
 
DropZoneCommented:
>> Im assuming this is rather like a javascript script or CSS file that just contains the functions and nothing else.  Is this correct?

This is correct, except that it executes at the server-side.  The file will then be included (just like you do with javascript libraries) on any page that requires it, by using the Server-Side-Include reference.

>>The @ command must be the first command within the Active Server Page.
/securitytest/logon.asp, line 4

The Option Explicit line must be the first line of code, and any @xxx directives need to be at the very top of the page.  Try this instead:

<%
    @LANGUAGE="VBSCRIPT" CODEPAGE="1252"
    Option Explicit
%>
<!--#include file="Connections/conHospital.asp" -->
' Set your LCID here. For instance, '1033' is US-English regional setttings (default)
<% Session.LCID = 2057 'English regional setttings %>

Its well recommended that you include the Option Explicit directive at the top of every script page.  What it does is to enforce the declaration of all variables and objects.  This means that you will need to have a "Dim" statement for each variable you use on the page.  This may sound like more work, but it actually helps in preventing typos and copy+pasting errors by generating an error if you introduced a variable name without it being defined.

     -dZ.
0
 
NorthDorsetWebAuthor Commented:
Hi there I have changed it as suggested but now get the following error:

The specified 'Option Explicit ' option is unknown or invalid.
/securitytest/logon.asp, line 3

Apologies if you reply and I dont this afternoon, I have to go to a meeting :(

Kind regards
Emma
0
 
DropZoneCommented:
I am not currently at a Windows computer, so I cannot test this, but just go ahead and remove the Option Explicit for the moment.

In any case, this should work:
<%@ LANGUAGE="VBSCRIPT" %>
<% Option Explicit %>

That's how I use it.  Everything else must be below it.

     -dZ.
0
 
DropZoneCommented:
Here's some information on Option Explicit:
http://www.4guysfromrolla.com/webtech/faq/Intermediate/faq6.shtml

     -dZ.
0
 
NorthDorsetWebAuthor Commented:
Ok i that worked:    <%@ LANGUAGE="VBSCRIPT" %>
                               <% Option Explicit %>

Now the form on logon.asp page is now posting to t_login.asp -   on my original site it was sending to loggedin.asp - I have changed the loggedin.asp file to t_login.asp.  This is the code at the top of my page as per your instructions for main.asp and any other pages:

<%@LANGUAGE="VBSCRIPT" CODEPAGE="1252"%>
<%Option Explicit%>
<!--#include file="Connections/conHospital.asp" -->
' Set your LCID here. For instance, '1033' is US-English regional setttings (default)
<% Session.LCID = 2057 'English regional setttings %>

<!-- #include virtual="securitytest/auth_lib.asp" -->

<%
      ' Authenticate our session.  If it failed, it will
      ' redirect automatically to the login page.
      ' Otherwise it continues as if nothing happened.
      Call AuthenticateSession()
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"


It is saying that the page cannot be found and the error in the address bar is:

http://pctwebs/login.asp?error=ERR_SESSION

I think this is a path problem at the posting of the form but whatever i seem to do - doesnt seem to help it.  I have to include securitytest/authlib.asp at the include virtual - otherwise it wont find the file.  But normally the pages direct to the correct file.  I think it shoudl be lokoing for:

http://pctwebs/securitytest/login.asp?error=ERR_session 

So the securitytest (the name of teh site) seems to be missing.

Knid regards
Emma
0
 
effxCommented:
lol, ill leave you guys to sort this out, my method was much easier to impliment speak soon when you cannot get this working.
0
 
effxCommented:
try this instead ;-)

<!-- #include virtual="/securitytest/auth_lib.asp" -->
0
 
DropZoneCommented:
NorthDorsetWeb:  A few points to consider.  I mentioned these things in my comments on the code above.

1. The error seems to be that the redirection URL was not found.  Make sure you have the correct URL for the login page for the constant C_LOGIN_PAGE_URL in auth_lib.asp.  In my example, "t_login.asp" and "login.asp" are supposed to be the same thing, the "t_" was a typo, sorry.

2. Also, my code example posts the login page to itself and then redirects to the "main" page if it passes authentication.  You can easily modify this to post to a separate page, but this is not necessary.

3. The virtual path in the #include directive should point to the path where you put the auth_lib.asp.

4. You cannot call AuthenticateSession() from the Login page nor from the page that processes the login (if they are different).  That function will authenticate the user once he is logged in.  If you call it before the user has been authenticated, it will automatically redirect you back to the login page in an endless loop.

5. Another thing is that you should include the auth code before any other code or server-side-include, to make sure the user is authenticated before any further page processing is done. The auth_lib code performs its own database connection, it just needs to have the Connection String constant set up properly.



effx:  Your method relied on storing the username and password in plaintext in a cookie which, as I explained, is not secure at all.  My method is actually very simple, residing wholly on a server-side-include file; he just needs to integrate it into his current code.  This is more maintainable, re-usable, and more secure.  Plus, if in the future he wants to add further security and encryption, he just needs to modify specific methods in the auth_lib file, instead of having to go hack around the entire code base.

     -dZ.
0
 
effxCommented:
Just one correction on your statement he is actually a she
0
 
DropZoneCommented:
>> Just one correction on your statement he is actually a she

Whoops!  There's no possible way for me to have known that.  But now I know.

       -dZ.
0
 
NorthDorsetWebAuthor Commented:
>> 1. The error seems to be that the redirection URL was not found.  Make sure you have the correct URL for the login page for the constant C_LOGIN_PAGE_URL in auth_lib.asp.  In my example, "t_login.asp" and "login.asp" are supposed to be the same thing, the "t_" was a typo, sorry.

I have changed this now and the page seems to be sending to itself as I am now receiving an error.  I changed it in the auth_lib.asp file ( Const C_LOGIN_PAGE_URL = "securitytest/logon.asp") and also in the logon.asp - <form action="logon.asp" method="POST">

The error is:  Error: ERR_DBCMD  Which from your notes above means  An error occurred executing the database statement.  Im not sure what this means.

>>  2. Also, my code example posts the login page to itself and then redirects to the "main" page if it passes authentication.  You can easily modify this to post to a separate page, but this is not necessary.

I have created the main.asp page now although its not getting that far because of the above error.

>> 3. The virtual path in the #include directive should point to the path where you put the auth_lib.asp.  

Yes this was pointing to the correct file - It was when i thought that the path was wrong above I used this as an example, it was in fact the "t_login.asp" file that was the typo causing problems.

<< 4. You cannot call AuthenticateSession() from the Login page nor from the page that processes the login (if they are different).  That function will authenticate the user once he is logged in.  If you call it before the user has been authenticated, it will automatically redirect you back to the login page in an endless loop.

Im not sure what you mean by this - have I called the AuthenticateSession from this page I have checked and I cant see it?  I literally copied your code from the above message.  I did put the authenticate session on "t_login.asp" which i thought i needed, I have now saved this page as main.asp.

5. Another thing is that you should include the auth code before any other code or server-side-include, to make sure the user is authenticated before any further page processing is done. The auth_lib code performs its own database connection, it just needs to have the Connection String constant set up properly.

So in main.asp should the Authenticate session go after option explicit as I have detailed below? And should this code be placed on every page that needs authenticated in that particular order?

<%@LANGUAGE="VBSCRIPT" CODEPAGE="1252"%>
<%Option Explicit%>
<%
      ' Authenticate our session.  If it failed, it will
      ' redirect automatically to the login page.
      ' Otherwise it continues as if nothing happened.
      Call AuthenticateSession()
%>

<!--#include file="Connections/conHospital.asp" -->
' Set your LCID here. For instance, '1033' is US-English regional setttings (default)
<% Session.LCID = 2057 'English regional setttings %>
<!-- #include virtual="securitytest/auth_lib.asp" -->


I really do appreciate your help on this - and yes, being a girl - its obviously a lot harder for me... hehehehehe :)

Emmxx
0
 
DropZoneCommented:
>> The error is:  Error: ERR_DBCMD  Which from your notes above means  An error occurred executing the database statement.  Im not sure what this means.

It means exactly that: there was an error performing the query.  There are no details because the code I sent you was a "no-frills" solution.  It had plenty of comments with suggestions on how to improve it.

In any case, if you want to know what the exact error was, do the following:
Find the following section in the LoginUser() function (in auth_lib.asp):

            ' Check to see if there were any errors
            If (Err.Number <> 0) OR (objConn.Errors.Count > 0) Then
               ' and error occurred! handle it!
               ' you may want to loop through the Errors
               ' collection to discover them

                  strError = "ERR_DBCMD"
            ElseIf .....

And right there where it sets strError add this:

      Response.Write "ASP ERROR:[" & Err.Description & "]<br>"
      Response.Write "DB ERROR:[" & objConn.Errors(0).Description & "]<br>"

That will display the error message(s) for you.  Note that you do this right now only to check it -- you do not want to leave that code there forever.  Also, in the future, you may want to log the errors, or handle them differently.

A few things that may help solving the issue:
1. As my "Assumptions" list mentioned, make sure that your connection string is properly set in the MM_conSWRMC_STRING constant -- and that that constant is defined either in auth_lib.asp, or somewhere where auth_lib.asp can access it.  The point is that a valid connection string should be set *before* LoginUser() attempts to connect to the database.  I used the name MM_conSWRMC_STRING because that's what you had in your old code.  If need be, at least for the moment, you can declare this constant with the proper value on top of auth_lib.asp.

2. Also mentioned in the assumptions is that the validation SQL query was correct.  You may want to check it to make.  It is currently set as:

      "SELECT *  FROM tblMembers  WHERE Username=? AND Password=?"

where the "?" symbols represent the parameters.


>> Im not sure what you mean by this - have I called the AuthenticateSession from this page I have checked and I cant see it?  I literally copied your code from the above message.  I did put the authenticate session on "t_login.asp" which i thought i needed, I have now saved this page as main.asp.

AuthenticateSession() should be called on "main.asp" and any other page that you want to protect.  Only the "Login" page should not have this call -- because it is the one that is going to authenticate -- it uses LoginUser() for this.  If I understand your comment correctly, you have set this properly.

>> So in main.asp should the Authenticate session go after option explicit as I have detailed below? And should this code be placed on every page that needs authenticated in that particular order?

The order of things is as follows:
1. First include any @ directives
2. Then put Option Explicit (which is optional, by the way, but very helpful)
3. Then comes the #include directive for auth_lib.asp
4. Then comes the AuthenticateSession() call
5. Then comes everything else.

The reason for the first 2 is because the language parser requires those two things to be (if included) before any code.  The reason for the rest is to ensure that AuthenticateSession() is the first thing that is done, and that if it fails, no other processing takes place.  the #include for auth_lib.asp should go before AuthenticateSession because that is where the function is defined.

So, in your "main.asp", the top of the page should look like this:

<%@LANGUAGE="VBSCRIPT" CODEPAGE="1252"%>
<%Option Explicit%>
<!-- #include virtual="securitytest/auth_lib.asp" -->
<%
      ' Authenticate our session.  If it failed, it will
      ' redirect automatically to the login page.
      ' Otherwise it continues as if nothing happened.
      Call AuthenticateSession()
%>

<!-- EVERYTHING ELSE GOES BELOW HERE -->

<!--#include file="Connections/conHospital.asp" -->
' Set your LCID here. For instance, '1033' is US-English regional setttings (default)
<% Session.LCID = 2057 'English regional setttings %>


>> I really do appreciate your help on this - and yes, being a girl - its obviously a lot harder for me... hehehehehe :)

Naw, it has nothing to do with being a girl -- we've all inexperienced at things new to us :)

I hope this helps.  I'm sorry for the confusion, but please understand that I cannot see your code, so when something fails on your side its hard for me to know if there's a typo or a variable set wrong.

    -dZ.
0
 
DropZoneCommented:
>> >> Just one correction on your statement he is actually a she
>> Whoops!  There's no possible way for me to have known that.  But now I know.

Correction:  I should have noticed the signature "Emma" in your comments above; my apologies.

     -dZ.
0
 
effxCommented:
:-)
0
 
NorthDorsetWebAuthor Commented:
Hi there, I do appreciate your help and Im really trying to understand what im doing some of it is over my head at the moment so please bare with me.

Ok I have added the error description check but it doesnt seem to be producing a full description - it still shows the basic error.  This is the section of code in the login user section, is this correct?

 ' Check to see if there were any errors
            If (Err.Number <> 0) OR (objConn.Errors.Count > 0) Then
               ' and error occurred! handle it!
               ' you may want to loop through the Errors
               ' collection to discover them

                strError = "ERR_DBCMD"
                Response.Write "ASP ERROR:[" & Err.Description & "]<br>"
                Response.Write "DB ERROR:[" & objConn.Errors(0).Description & "]<br>"

                ElseIf NOT (objRecSet.BOF AND objRecSet.EOF) Then
                  strMemberID = objRecSet("MemberID")

>>>>>> 1. As my "Assumptions" list mentioned, make sure that your connection string is properly set in the MM_conSWRMC_STRING constant -- and that that constant is defined either in auth_lib.asp, or somewhere where auth_lib.asp can access it.  

Im using dreamweaver and this automatically includes the connection file on every page.  So at the top of each page I have:

<%@LANGUAGE="VBSCRIPT" CODEPAGE="1252"%>
<% Option Explicit %>
%>
<!--#include file="Connections/conHospital.asp" -->
' Set your LCID here. For instance, '1033' is US-English regional setttings (default)
<% Session.LCID = 2057 'English regional setttings %>
<!-- #include virtual="securitytest/auth_lib.asp" -->

This is the code within the conHospital.asp file:

<%
' FileName="Connection_odbc_conn_dsn.htm"
' Type="ADO"
' DesigntimeType="ADO"
' HTTP="false"
' Catalog=""
' Schema=""
Dim MM_conHospital_STRING
MM_conHospital_STRING = "DRIVER={Microsoft Access Driver (*.mdb)};DBQ=E:\database\ITBook.mdb"
%>


>>  Also mentioned in the assumptions is that the validation SQL query was correct.  You may want to check it to make.  It is currently set as:
      "SELECT *  FROM tblMembers  WHERE Username=? AND Password=?"
where the "?" symbols represent the parameters.

Ahhh... ok ive left the ? in...... now  ive checked my original script on the original site and the SQL query was referred to cUsername and cPassword.  Now this was set up in the script that im no longer using so I cant see that it will be relevant now- therefore Im not sure what the parameters should be.  You have set up strUsername and strPassword which request the values from the form within the login user function - could these be the parameters?

>>>>>>>>>> AuthenticateSession() should be called on "main.asp" and any other page that you want to protect.  Only the "Login" page should not have this call -- because it is the one that is going to authenticate -- it uses LoginUser() for this.  If I understand your comment correctly, you have set this properly.

yes im sure i have this correct too

>>>>>>>>>.The reason for the first 2 is because the language parser requires those two things to be (if included) before any code.  The reason for the rest is to ensure that AuthenticateSession() is the first thing that is done, and that if it fails, no other processing takes place.  the #include for auth_lib.asp should go before AuthenticateSession because that is where the function is defined.

Horrayyy - I completely understand this bit!

>>>>>>>>>>>I hope this helps.  I'm sorry for the confusion, but please understand that I cannot see your code, so when something fails on your side its hard for me to know if there's a typo or a variable set wrong.

You are being extremely helpful and im just worried im taking up too much of your time.  I really do appreciate this - and as I said earlier whilst I dont underwstand it all - im getting there!

emmax


0
 
DropZoneCommented:
>> Hi there, I do appreciate your help and Im really trying to understand what im doing some of it is over my head at the moment so please bare with me.

No problem, I'm here to help.

>> Ok I have added the error description check but it doesnt seem to be producing a full description - it still shows the basic error.  This is the section of code in the login user section, is this correct?

OOPS!  That's my mistake:  since you are redirecting right after the error is displayed, you won't see the error message.  For testing purposes, comment out the Response.Redirect call, so that when a failure occurs it just stays there with the error message.

As for the code section, yes you are correct, that is the place to put the lines.  If this all seems convoluted, just remember that you only have a skeleton code base from which to build a more robust application in the future.  Once you have more time for it, adding a logging mechanism in those parts will give you visibility of what's wrong without having to change your code to debug it (like now).  The code I gave you has all the pieces in place so that in the future you can extend it easily (instead of having to muck all about the code adding error checking).  But for the moment, we're going bare-bones.

>> MM_conHospital_STRING = "DRIVER={Microsoft Access Driver (*.mdb)};DBQ=E:\database\ITBook.mdb"

That looks fine.  Just make sure the #include for conHospital.asp is always before the include for auth_lib.asp, which requires this value.  Your code seems to do this.

>> therefore Im not sure what the parameters should be.  You have set up strUsername and strPassword which request the values from the form within the login user function - could these be the parameters?

I am sorry about this, perhaps I should have explained:  The '?' symbols are literal; that is, you leave them as question marks in the string.  When you execute the query, the parser will replace the '?' symbols with the parameters in the collection, in the order they are found.  The code I sent you does this already, and you do not need to change it.

What you need to make sure is that the query is correct: that the table is called tblMembers and that the appropriate columns are Username and Password.

>> You are being extremely helpful and im just worried im taking up too much of your time.  I really do appreciate this - and as I said earlier whilst I dont underwstand it all - im getting there!

No worries.  As long as you learn and understand what you are doing, its cool.  I hate just posting an answer that says "here you go, use this" and leaving people with a weird sense of "magic happens here".

     Cheers!
     -dZ.
0
 
NorthDorsetWebAuthor Commented:
You advise commenting out the response redirect call:  I have the following on the auth_lib.asp file?

' --------------------------------------
' -- Redirect to Login Screen
' --------------------------------------
Sub RedirToLogin(ByVal strErrCode)
      Response.Redirect(C_LOGIN_PAGE_URL & "?error=" & strErrCode)
End Sub

and the following on the login screen:

<%
Dim ERROR_CODE : ERROR_CODE = ""

      ' Check if the login form was submitted (i.e. the button was clicked)
      If Request.Form("btnLogin") <> "" Then
            ERROR_CODE = LoginUser()

            ' Login succeeded, redirect to main page!
            If ERROR_CODE = "" Then
                  Response.Redirect("/main.asp")
            End If
      Else
            ' Get the error code from the query string (if any)
            ERROR_CODE = Request.QueryString("error")
      End If

%>


Which bits do i comment out?
0
 
DropZoneCommented:
Comment this (for the moment, while we discover what the error is):

Sub RedirToLogin(ByVal strErrCode)
      ' DEBUG: This line is now commented.
      ' Response.Redirect(C_LOGIN_PAGE_URL & "?error=" & strErrCode)
End Sub
0
 
NorthDorsetWebAuthor Commented:
Thanks - done that - its not showing the full error yet.  This is the code i amended:

' --------------------------------------
' -- Redirect to Login Screen
' --------------------------------------
Sub RedirToLogin(ByVal strErrCode)
        'DEBUG:  This line has now been commented
      'Response.Redirect(C_LOGIN_PAGE_URL & "?error=" & strErrCode)
End Sub
0
 
DropZoneCommented:
What error are you actually getting? Can you post your Login page code?

   -dZ.
0
 
NorthDorsetWebAuthor Commented:
Ok sure:

<%@LANGUAGE="VBSCRIPT" CODEPAGE="1252"%>
<% Option Explicit %>
%>
<!--#include file="Connections/conHospital.asp" -->
' Set your LCID here. For instance, '1033' is US-English regional setttings (default)
<% Session.LCID = 2057 'English regional setttings %>
<!-- #include virtual="securitytest/auth_lib.asp" -->

<%
Dim ERROR_CODE : ERROR_CODE = ""

      ' Check if the login form was submitted (i.e. the button was clicked)
      If Request.Form("btnLogin") <> "" Then
            ERROR_CODE = LoginUser()

            ' Login succeeded, redirect to main page!
            If ERROR_CODE = "" Then
                  Response.Redirect("/main.asp")
            End If
      Else
            ' Get the error code from the query string (if any)
            ERROR_CODE = Request.QueryString("error")
      End If

%>


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><!-- InstanceBegin template="/Templates/template.dwt" codeOutsideHTMLIsLocked="false" -->
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<!-- InstanceBeginEditable name="doctitle" -->
<title>IT Department Fault Reporting</title>
<!-- InstanceEndEditable --><!-- InstanceBeginEditable name="head" -->
<link href="style.css" rel="stylesheet" type="text/css">
<!-- InstanceEndEditable -->
<link href="/../style.css" rel="stylesheet" type="text/css">
<SCRIPT TYPE="text/javascript">
<!--
function popup(mylink, windowname)
{
if (! window.focus)return true;
var href;
if (typeof(mylink) == 'string')
   href=mylink;
else
   href=mylink.href;
window.open(href, windowname,'width=700,height=750,scrollbars=yes');
return false;
}
//-->
</SCRIPT>

<style type="text/css">
<!--
a:hover {
      color: #993333;
}
.style1 {color: #000000}
-->
</style>
</head>

<body onload="initPage()">
<div align="center">
  <table width ="700" border="0" cellpadding="0" cellspacing="0" id="maintable">
   
   
    <tr bordercolor="#FFFFCC">
      <td><div align="center"><img src="images/banner2.jpg" alt="Dorset PCT" width="692" height="93"></div></td>
    </tr>
    <tr align="left" valign="middle" bgcolor="#6633FF" id="menubar">
      <td bgcolor="#6666FF" id="menubar"><h2 align="center">IT Department Fault Reporting</h2>
      </td>
    </tr>
    <tr>
      <td><div align="center"><!-- InstanceBeginEditable name="EditRegion5" -->
        <p>&nbsp;</p>
        <!-- InstanceEndEditable --></div></td>
    </tr>
    <tr>
      <td>
        <!-- InstanceBeginEditable name="Content" -->
        <%
      If ERROR_CODE <> "" Then
            ' Of course, you may want to display user-friendly errors
            Response.write "<p>Error: " & ERROR_CODE & "</p>"
      End If
%>
      <form action="logon.asp" method="POST">
            <table width="500" border="0" cellspacing="0" cellpadding="4">
              <tr>
                <td><strong>Login</strong>:</td>
                <td><input type="text" name="username" value=""></td>
              </tr>
              <tr>
                <td><strong>Password</strong>:</td>
                <td><input type="text" name="password" value=""></td>
              </tr>
              <tr>
                <td>&nbsp;</td>
                <td><input type="submit" name="btnLogin" value="Login"></td>
              </tr>
            </table>
      </form>
        <!-- InstanceEndEditable --></td>
    </tr>
    <tr>
      <td><h6 align="center"><strong>Dorset Primary Care Trust : IT Department </strong></h6></td>
    </tr>
  </table>
</div>
</body>
<!-- InstanceEnd --></html>
0
 
DropZoneCommented:
I see nothing wrong with your code, and the error message should be displayed at the top of the page.  Perhaps it is masked by the content, so view the source of the html page and see if you can find "ASP ERROR:" or "DB ERROR:" somewhere at the top.

     -dZ.
0
 
NorthDorsetWebAuthor Commented:
This appears at the top of the view source file:

%>

' Set your LCID here. For instance, '1033' is US-English regional setttings (default)
ASP ERROR:[Variable is undefined]<br>

then it goes to DOCTYPE...... etc...
0
 
DropZoneCommented:
Well, there you go: the error message is that a variable was used without being defined (that's what the Option Explicit enforces).

Since I tested the code and made sure that all variables were defined, the only "stray" one I see is the connection string variable, which is not defined in my code, but depended on your old code defining it.  I put in my code "MM_conSWRMC_STRING" because that's what shows up in your original question.  However, your recent comment suggests that the connection string variable is "MM_conHospital_STRING".  You may want to revise this so that both match.

Let me know if there are any other errors after this.

     -dZ.
0
 
NorthDorsetWebAuthor Commented:
AHHHH i see i thought that there was a variable missing so the error message couldlnt be produced.

The MM_conHospital_STRING is defined in the connections file as follows:

<%
' FileName="Connection_odbc_conn_dsn.htm"
' Type="ADO"
' DesigntimeType="ADO"
' HTTP="false"
' Catalog=""
' Schema=""
Dim MM_conHospital_STRING
MM_conHospital_STRING = "DRIVER={Microsoft Access Driver (*.mdb)};DBQ=E:\database\ITBook.mdb"
%>

I have changed the sections of the code in both the login and auth_lib.asp files but the same error is still beign produced and checking the source code suggests it is still a dodgy undefined variable somewhere.

kind regards
emma
0
 
DropZoneCommented:
>> I have changed the sections of the code in both the login and auth_lib.asp files but the same error is still beign produced[...]

which section of the code?  I don't recall the connection string being used in the login file.

The lines you needed to change were in the auth_lib file:

      ' Initialize the connection
      '   -----
      '   NOTE:  I assume MM_conSWRMC_STRING is a valid connection string
      '   -----
            objConn.CursorLocation    = adUseServer
            objConn.ConnectionString  = MM_conHospital_STRING ' <<<< CHANGED!
            objConn.ConnectionTimeout = 30
            objConn.CommandTimeout    = 30
            objConn.Open MM_conHospital_STRING ' <<<< CHANGED TOO!

Also, it could be that the VB constants I'm using in the code may not be in the global namespace.  To do that you need to add the following line at the very top of your global.asa file:

<!-- METADATA
            TYPE="TypeLib"
            NAME="Microsoft ActiveX Data Objects 2.6 Library"
            UUID="{00000206-0000-0010-8000-00AA006D2EA4}"
            VERSION="2.6"
-->

That will import all the VB constants into the application's namespace.  Otherwise, you won't be able to use things like "adUseServer", "adVarChar", or "adParamInput".

If none of this helps, please post your auth_lib code.

    -dZ.
0
 
DropZoneCommented:
Any news?
0
 
NorthDorsetWebAuthor Commented:
Sorry for the delay in responding.  You were right i couldnt see the MM_conHospital_STRING in the logon page.  Must have had a blonde moment!

Im not using a Global.asa file.  Is there somewhere else I can put the code you suggest?

I also post the auth_lib code just in case there is something wrong here.

<%
      ' This points to your login page.  It will be used in automatic redirections
      Const C_LOGIN_PAGE_URL = "/logon.asp"

' --------------------------------------
' -- Login User
' --------------------------------------
Function LoginUser
      Dim objConn
      Dim objCmd
      Dim objRecSet
      Dim objParam
      Dim objErr
      Dim strUsername
      Dim strPassword
      Dim strMemberID
      Dim strError

      ' Default to failure
      strError     = "ERR_INVALID"
      strUsername  = Request.Form("username")
      strPassword  = Request.Form("password")

      ' If for some reason this user is logged in, close the session
      Session.Contents.RemoveAll()

      If (strUsername = "") OR (strPassword = "") Then Exit Function

      ' Ignore errors when they happen so that we can detect them manually
      On Error Resume Next

      ' Initialize the Connection and Command objects
      '
      ' Use a command object instead of a RecordSet object.
      ' The command object will return a recordset.
      Set objConn = Server.CreateObject("ADODB.Connection")
      Set objCmd  = Server.CreateObject("ADODB.Command"   )

      ' Initialize the connection
      '   -----
      '   NOTE:  I assume MM_conHospital_STRING is a valid connection string
      '   -----
            objConn.CursorLocation    = adUseServer
            objConn.ConnectionString  = MM_conHospital_STRING
            objConn.ConnectionTimeout = 30
            objConn.CommandTimeout    = 30
            objConn.Open MM_conHospital_STRING

      ' Continue if the connection is active
      If (objConn.State <> adStateClosed) Then
            ' Initialize the command
                  objCmd.ActiveConnection = objConn
                  objCmd.CommandText      = "SELECT *  FROM tblMembers  WHERE Username=? AND Password=?"

            ' Initialize the parameters
            ' Username
            Set objParam = objCmd.CreateParameter("Username")
                  objParam.Type      = adVarChar
                  objParam.Value     = strUsername
                  objParam.Direction = adParamInput
                  objParam.Size      = Len(strUsername)
            objCmd.Parameters.Append objParam

            ' Password
            Set objParam = objCmd.CreateParameter("Password")
                  objParam.Type      = adVarChar
                  objParam.Value     = strPassword
                  objParam.Direction = adParamInput
                  objParam.Size      = Len(strPassword)
            objCmd.Parameters.Append objParam

            Set objParam = Nothing

            ' Execute the query and get the record set
            objCmd.Prepared = True
            Set objRecSet = objCmd.Execute( , , adCmdText)

            ' Check to see if there were any errors
            If (Err.Number <> 0) OR (objConn.Errors.Count > 0) Then
               ' and error occurred! handle it!
               ' you may want to loop through the Errors
               ' collection to discover them

                  strError = "ERR_DBCMD"
                          Response.Write "ASP ERROR:[" & Err.Description & "]<br>"
                          Response.Write "DB ERROR:[" & objConn.Errors(0).Description & "]<br>"

            ElseIf NOT (objRecSet.BOF AND objRecSet.EOF) Then
                  strMemberID = objRecSet("MemberID")

                  If (strMemberID <> "") Then
                        ' We found the user!
                        strError = ""

                        ' Initialize the Authorized Session.
                        ' You may want to store other user information here
                        Session("AUTH_USER") = strMemberID

                        ' Preferrably, you would store an encrypted token
                        ' which would then be also sent as a cookie and
                        ' then validated on each request.
                  End if
            End If

            objRecSet.Close()
            objConn.Close()
      Else
            ' You may want to log these errors.

            strError = "ERR_DBCONN"
      End If

      set objRecSet = Nothing
      set objCmd    = Nothing
      set objConn   = Nothing

      ' Disable ignore errors
      On Error Goto 0

      LoginUser = strError
End Function

' --------------------------------------
' -- Logout User
' --------------------------------------
Sub LogoutUser
      ' If you set an Auth Cookie, you should delete it here

      ' Clear the session
      Session.Abandon()
      RedirToLogin "ERR_LOGOUT"
End Sub

' --------------------------------------
' -- Redirect to Login Screen
' --------------------------------------
Sub RedirToLogin(ByVal strErrCode)
        'DEBUG:  This line has now been commented
      'Response.Redirect(C_LOGIN_PAGE_URL & "?error=" & strErrCode)
End Sub

' --------------------------------------
' -- Authenticate Session
' --------------------------------------
Sub AuthenticateSession
      Dim strAuthUser

      strAuthUser = Session("AUTH_USER")

      ' If you set an Auth Cookie you should decrypt it and
      ' validate it here against the token stored in the session.

      If (strAuthUser = "") Then
            Session.Abandon()
            RedirToLogin "ERR_SESSION"
      End If
End Sub
%>
0
 
DropZoneCommented:
>> Im not using a Global.asa file.  Is there somewhere else I can put the code you suggest?

Just create a Global.asa file in the root directory of your ASP application and put that code in it.  That's it.  The other way is to use a server-side-include directive on every page to import the VB constants file, then you'll have to deploy that file with your project.  I suggest the Global.asa way because it is easier.

Did it work after you changed the connection string?  If not, what error are you getting now? (Recall to uncomment the line in RedirToLogin() once the errors stop so that you are redirected after logging in correctly.)

     -dZ.
0
 
NorthDorsetWebAuthor Commented:
Ahah!!!!  Now im not sure whether its because i put the global asa file in but I am now redirecting properly to the main page.  So that bit is working properly now.

So the code that I have in the logon page is only for the logon page.  I read through your notes and have now created another page and have put the following code in the head of each page which calls to authenticate before it displays to the user.  So therefore if Im right any additional pages will need this code.

<%
      ' Authenticate our session.  If it failed, it will
      ' redirect automatically to the login page.
      ' Otherwise it continues as if nothing happened.
      Call AuthenticateSession()
%>

So when i log in using a correct username and password it is now going to the main page and I can also access the new page from here or the home page.  

What is happening now is that if i put the wrong user name in, I was getting the ERR_INVALID error displayed on the logon page. However, having thought about this I have found the string where the ERR_INVALID was set and I have changed this to say You have entered the wrong username or password..... So thats good and I will be able to trace the other error messages and put userfriendly messages in there.

The only thing I can see wrong now is if I click the new page which is calling the authenticate procedure having put a wrong username or password in, it is redicting me to the following:

http://pctwebs/logon.asp?error=ERR_SESSION 

And all Im getting a Page cannot be found error.

Kind regards
Emma
0
 
DropZoneCommented:
>> Ahah!!!!  Now im not sure whether its because i put the global asa file in but I am now redirecting properly to the main page.  So that bit is working properly now.

Good, progress!

>> I read through your notes and have now created another page and have put the following code in the head of each page which calls to authenticate before it displays to the user.  So therefore if Im right any additional pages will need this code.

This is correct.  Actually, you need the #include directive for the auth_lib file, too:

<!-- #include virtual="securitytest/auth_lib.asp" -->
<%
      ' Authenticate our session.  If it failed, it will
      ' redirect automatically to the login page.
      ' Otherwise it continues as if nothing happened.
      Call AuthenticateSession()
%>

>> So thats good and I will be able to trace the other error messages and put userfriendly messages in there.

Hum, if I understand your comment correctly, I wouldn't recommend doing that.  The idea of using ERR_INVALID and the like as error messages is because they will get sent in the QueryString as part of the redirection, like:
    http://pctwebs/logon.asp?error=ERR_INVALID
and you do not want to send a big user-friendly string there.  I suggest you leave those error messages as they are, and include in your Login page something like this:

<%
      Dim strErrorMsg

      ' After authentication, dispay an error if necessary

      If ERROR_CODE <> "" Then
            ' Display user-friendly errors based on the error code
          Select Case ERROR_CODE
              Case "ERR_INVALID"
                    strErrorMsg = "Invalid username or password.  Please try again."
              Case "ERR_DBCMD"
                    strErrorMsg = "A database error occurred."
              Case "ERR_DBCONN"
                    strErrorMsg = "Error connecting to the database."
              Case "ERR_SESSION"
                    strErrorMsg = "Invalid or expired session.  Please log in."
              Case "ERR_LOGOUT"
                    strErrorMsg = "Your session has been terminated.  Enter your username and password to log-in again"
              Case Else
                    strErrorMsg = "Unknown error.  Please contact administrator."
          End Select

          ' Display the error message
          Response.write "<b>" & strErrorMsg & "</b>"
      End If
%>

(This is why my Login.asp code had a comment like "Of course, you may want to display user-friendly errors".)

That way if you ever need to change the error messages, you can do it on a single place, instead of having to hunt them down.  Also, they can be as long and friendly as you want, without having to encode them in the QueryString.

>> The only thing I can see wrong now is if I click the new page which is calling the authenticate procedure having put a wrong username or password in, it is redicting me to the following:

I'm confused.  Why are you clicking on a "secure" page if the authentication failed?  Ideally, the user should not have access to any link to secure pages without being logged in.  However, the behaviour you described is correct:  if you try to access a "secure" page without proper authentication, you will be redirected to the login page with the error code "ERR_SESSION", which means that your session is invalid (and you need to log in).

If you are getting a Page Not Found error, its probably because the C_LOGIN_PAGE_URL constant is not set up properly.  Make sure that it points to your Login page.

Other than that, you seem to be good to go.  Let me know if there is any further problems :)

    -dZ.
0
 
NorthDorsetWebAuthor Commented:
Right I feel that Im nearly there.  Yes the C>LOGIN_PAGE_URL constant was set to /logon.asp rather than logon.asp.  It is now redirecting correctly.  

Just to clarify:
"I'm confused.  Why are you clicking on a "secure" page if the authentication failed?  Ideally, the user should not have access to any link to secure pages without being logged in.  However, the behaviour you described is correct:  if you try to access a "secure" page without proper authentication, you will be redirected to the login page with the error code "ERR_SESSION", which means that your session is invalid (and you need to log in)"

On one or two of my sites some pages are open to all and some will be open to only those who can sign in.  Possibly this is not the best way of doing it and maybe I should have a separate menu for those who are signed in - but at the moment thats too much for me to think about :)

Testing the page using an incorrect username and password Im still getting an ERR_INVALID error message writing to the page.   I have added your script above which writes user friendly errors after changing back the userfriendly message i added to ERR_INVALID.  Im thinking that I need to tie in th enew script with the response.write on the logon page.  Here is my code for those bits.  

In the head:

<%
Dim ERROR_CODE : ERROR_CODE = ""

      ' Check if the login form was submitted (i.e. the button was clicked)
      If Request.Form("btnLogin") <> "" Then
            ERROR_CODE = LoginUser()

            ' Login succeeded, redirect to main page!
            If ERROR_CODE = "" Then
                  Response.Redirect("main.asp")
            End If
      Else
            ' Get the error code from the query string (if any)
            ERROR_CODE = Request.QueryString("error")
      End If

%>

<%
      Dim strErrorMsg

      ' After authentication, dispay an error if necessary

      If ERROR_CODE <> "" Then
            ' Display user-friendly errors based on the error code
          Select Case ERROR_CODE
              Case "ERR_INVALID"
                    strErrorMsg = "Invalid username or password.  Please try again."
              Case "ERR_DBCMD"
                    strErrorMsg = "A database error occurred."
              Case "ERR_DBCONN"
                    strErrorMsg = "Error connecting to the database."
              Case "ERR_SESSION"
                    strErrorMsg = "Invalid or expired session.  Please log in."
              Case "ERR_LOGOUT"
                    strErrorMsg = "Your session has been terminated.  Enter your username and password to log-in again"
              Case Else
                    strErrorMsg = "Unknown error.  Please contact administrator."
          End Select

          ' Display the error message
          Response.write "<b>" & strErrorMsg & "</b>"
      End If
%>

In the body:

<%
Dim ERROR_CODE : ERROR_CODE = ""

      ' Check if the login form was submitted (i.e. the button was clicked)
      If Request.Form("btnLogin") <> "" Then
            ERROR_CODE = LoginUser()

            ' Login succeeded, redirect to main page!
            If ERROR_CODE = "" Then
                  Response.Redirect("main.asp")
            End If
      Else
            ' Get the error code from the query string (if any)
            ERROR_CODE = Request.QueryString("error")
      End If

%>

thanks again for all of your help on this!
0
 
DropZoneCommented:
>> On one or two of my sites some pages are open to all and some will be open to only those who can sign in.  Possibly this is not the best way of doing it and maybe I should have a separate menu for those who are signed in - but at the moment thats too much for me to think about :)

That's fine.  Like I said, when the user clicks on one of the "secure" pages, he'll get redirected to the login screen which is expected.  The user should know what to do from there on.

About the error message.  I don't understand what you mean by "in the head" and "in the body".

There is only one place where you put that code: in the Login page, right after performing the authentication, but before rendering the login form itself (so that the validation and error message occur before it).

Without looking at your code, I cannot tell exactly where to put it, but here is an example:

<%@LANGUAGE="VBSCRIPT" CODEPAGE="1252"%>
<% Option Explicit %>
%>
<!--#include file="Connections/conHospital.asp" -->
' Set your LCID here. For instance, '1033' is US-English regional setttings (default)
<% Session.LCID = 2057 'English regional setttings %>
<!-- #include virtual="securitytest/auth_lib.asp" -->
<%
      ' -------------------------
      ' Perform authentication
      ' -------------------------
      Dim ERROR_CODE  : ERROR_CODE  = ""

      ' Check if the login form was submitted (i.e. the button was clicked)
      If Request.Form("btnLogin") <> "" Then
            ERROR_CODE = LoginUser()

            ' Login succeeded, redirect to main page!
            If ERROR_CODE = "" Then
                  Response.Redirect("/main.asp")
            End If
      Else
            ' Get the error code from the query string (if any)
            ERROR_CODE = Request.QueryString("error")
      End If
%>
<html>
<head>
    <!-- HEAD TAGS GO HERE -->
</head>
<body>
<%
      Dim strErrorMsg

      ' -------------------------
      ' Dispay an error if necessary
      ' -------------------------
      If ERROR_CODE <> "" Then
            ' Prepare user-friendly errors based on the error code
            Select Case ERROR_CODE
                  Case "ERR_INVALID"
                        strErrorMsg = "Invalid username or password.  Please try again."
                  Case "ERR_DBCMD"
                        strErrorMsg = "A database error occurred."
                  Case "ERR_DBCONN"
                        strErrorMsg = "Error connecting to the database."
                  Case "ERR_SESSION"
                        strErrorMsg = "Invalid or expired session.  Please log in."
                  Case "ERR_LOGOUT"
                        strErrorMsg = "Your session has been terminated.  Enter your username and password to log-in again"
                  Case Else
                        strErrorMsg = "Unknown error.  Please contact administrator."
            End Select

            ' Display the error
            Response.Write "Error: <b>" & strErrorMsg & "</b>"
      End If
%>

<form>
      <!-- LOGIN FORM GOES HERE -->
</form>
</body>
</html>



One last thing:  You said that you replaced the C_LOGIN_PAGE_URL constant with "login.asp".  This may work now, but be aware that it implies a relative path from the current page.  This means that if you the RedirToLoginPage() Sub is called from a page inside a subdirectory, it won't be found.  It is best to use an absolute path from the root of the web site.  For example.  If your login page is in the "/auth/" directory, you would put "/auth/login.asp".  If it is in the root directory, then it should be "/login.asp", and so on.

     -dZ.
0
 
NorthDorsetWebAuthor Commented:
Hi there, sorry its taken me so long to get back to you - so much to do - so little time!

After checking your example I realised that I had put the error messages in the head of the page rather than within the body.  So yes its all working fine now.

One last thing.   I cant see anywhere that allows the user to log out - has this been included - is it just that I need to add a link to do this?
0
 
DropZoneCommented:
No problem.  I'm glad its all working now.

To logout, all you need to do is call the LogoutUser() Sub in the auth_lib.asp script.  You can do this from any place of your site (like, for example, if an error occurred and you want to forcibly logout the user).  A common thing to do is to put a link in your page that calls a logout.asp page, and in this page all you do is call LogoutUser() (after including the auth_lib.asp script at the top, of course).

That Sub will destroy the session and redirect the user to the login page with the ERR_LOGOUT code, so that a proper message is displayed.

   -dZ.
0
 
NorthDorsetWebAuthor Commented:
Woww.. i must be learning something - I managed to do that all by myself :)

Well thank you so much for your help on this I really have appreciated your patience.
0
 
DropZoneCommented:
I'm glad to be of assistance; its been my pleasure, really.  The important thing is that you learn and understand the principles, so that you can do it on your own next time.

    Good luck!
   -dZ.
0
 
NorthDorsetWebAuthor Commented:
HI Dropzone,
I hope that this is the correct way of contacting you I couldnt find any other way.

Well ive been successfully using your solution on a couple of sites and ive referred back to your help here quite a few times now.  Ive been able to solve all of the issues I had but tonight i have set up a site on my own space at home and i just cant seem to find out what the problem is.  It relates to the database error that i had before and ive displayed the error as a variable undefined.  Ive been through the code with a fine tooth comb - but i cant seem to spot where the variable is undefined.  Can you help me with this?
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.