CIS Logo SVC Logo

   Computing & Information Systems
   Department

 

Schoology Facebook        Search CIS Site      Tutorials

Online Survey Requiring Login



The Goals for this Example


We wish to create an online survey. In addition, we want to require authentication. In this case, we insist that the user supply a valid password in order to access the survey. We also want to see how to insert the submitted data in a table in SQL Server. We examine how to use secure communications so that the user's data is encrypted and the user can see a certificate that verifies that the web server is who it says it is. Finally, we wish to enable the user to logout when finished.

The Overall Design

  • Since this is a longer application than we have created before, it would be wise to create the overall design first, before looking at the details of the implementation. Follow the links to the screen shots to see how each page should look.
  • Home.aspx login page
    • Here the user must supply a valid username and password.
    • We will use required field validators to be sure that both a username and password are supplied.
    • In addition, regular expression validators will be used to be certain that both the username and password are the type of data that we expect and are not longer than we expect.
    • This is one way in which we defend against SQL injection attacks and other attacks in which the user supplies bad data to try to get the application to do something that we did not intend it to do. By default ASP .NET web apps will not let a user submit something in script tags in a text box. This is to prevent malicious users from getting some nasty script recorded in our database (and potentially displayed in some web application later).
    • A custom validator will be used. Its ServerValidate procedure will look up the username in a table in our SQL Server database, returning that user's password.
    • A stored procedure will be used for this lookup, in part to add another defense against SQL injection attacks.
    • If the returned password matches that which the user submitted, so-called forms authentication will be used to grant access to the survey and the user will be redirected to the survey page.
    • Any attempt to bypass the login page and go directly to the survey page will send the user to the login page.
  • Default.aspx survey page
    • The survey page will ask the user to submit his/her job title and salary.
    • Regular expression validators will again be used to be sure that the data is reasonable before submitting it to the database, while required field validators will make sure that the user puts something into each box.
    • If the data is fine, then a stored procedure (for security again) will be used to insert this data into the desired database table.
    • If the data is inserted, the user is redirected to the success page.
    • If the data is not inserted, perhaps because this user already submitted the survey data, then the user is redirected to the failure page.
    • We don't want a user to be able to submit survey data more than once. To enforce this we will make the username field to be the primary key for the table that holds the user data. Since a primary key field has to contain unique data and the data being submitted will consist of the username, job title, and salary, the database will refuse to insert more than one row of data for a given user.
  • Success page
    • This page tells the user that the data was recorded.
    • This page also allows the user to log out and return to the login page.
  • Failure page
    • This page tells the user that the data was not recorded.
    • This could be due to a database problem or to a user who is trying to submit survey data more than once.
    • As with the success page, the user is given a button to click in order to log out.

Making the Web App



Make a New Web App

  • Make a new ASP .NET web app project. We will assume that the name of the Project is Login. Store it in a convenient location, such as your M drive.
  • In Solution Explorer, right click on your app. Select Add, New Item. Then choose Web Form and name it Home.aspx.
  • In Source mode, change the title of this page to "Employment Survey Login Page".
  • Then switch to Design view.
  • Save your work so far by using File, Save All.

Database Preparations

  • We assume that you still have a logon for SQL Server and still have access to the database you used in the previous examples. In our example here the name used for the database is CS305, but the name of your database is no doubt different.
  • In Visual Studio, find Server Explorer and click on the + in front of your database connection, if need be, to expand it.
  • Then expand the Tables folder.
  • Next, right click on the Tables folder and select Add New Table.
  • Fill in the items shown in this picture. Use the types, etc. as shown. This data is also listed here for convenience:
Column Name Data Type Allow Nulls
Username nchar(8) no
Salary money no
Title nchar(24) no

  • Right click at the front of the Username field and choose Set Primary Key in order to make the Username field to be the primary key for this table.
  • This will prevent users of our web app from successfully submitting their data more than once, as the values for the primary key field must be unique.
  • Do File, Save and save this table under the name SurveyData.
  • Close the window where we designed this table.
  • We will not add data to this table now since that is what your web app will do.
  • Instead, make another new table. This one will hold the username and password for each user.
  • Fill in the 2 fields shown below and in this screen shot.
Column Name Data Type Allow Nulls
Username nchar(8) no
Password nchar(8) no

  • Set the Username field to be the primary key.
  • Save the table, naming it SurveyUsers.
  • Then close the window where we designed the table.
  • We do need to add data to this table.
  • Right click on your SurveyUsers table in Server Explorer and select Show Table Data.
  • In the resulting window you can fill in data for this table by typing over the top of the NULLs that you see. Fill in several rows, where each username consists of alphabetic characters and is up to 8 characters in length. The passwords for these should be exactly 8 characters in length, with alphabetic characters, digits, underscore, +, and = as the list of valid characters. (You can, of course, adjust these to suit your needs.)
  • You might, for example, enter the following set of data. After doing so, just close the inner window where you entered the data. It is saved automatically.
Username Password
smithc ATd83+ea
reyesj 4mda_uT2
robisonm Y=7tniw3

  • While we are working with the database, we should set up a relationship between the two tables to make sure that a user whose data is entered into the SurveyData table cannot have his entry deleted from the SurveyUsers table. This is called referential integrity. It is not greatly important in this case, but it can be very helpful in other cases in keeping the data from being put into an inconsistent state.
  • Right click on the SurveyData table in Server Explorer and select Open Table Definition.
  • Click on the Relationship button (or use Table Designer, Relationships).
  • Note that you get a dialog box for Foreign Key Relationships.
  • Click on the Add button.
  • This new relationship will be given some default name, which will be adjusted automatically.
  • Expand the Tables and Columns Specifications property. Click on the ... button that then appears. This will bring up a Table and Columns window where you can change a number of items.
  • In the box labelled "Primary key table" select the SurveyUsers table.
  • In the first box below this, click to get the pull-down and then select Username.
  • Here is a picture of the situtation.
  • The Foreign Key box will automatically contain the table name SurveyData, the one you right clicked on to start all of this.
  • Click on the first box beneath this to get the pull-down and then select Username.
  • If any other field names are shown, get rid of them by clicking on the box each is in and selecting None.
  • Make sure that the 2 versions of the Username field are on the same line.
  • What we have done is to relate the Username fields in the 2 tables.
  • Click on the OK button. This will take you back to the Properties window. Feel free to look through these properties.
  • Click on the Close button.
  • Then close the design window for the SurveyData table. You will be asked whether to save your changes. Say yes.
  • To see what this relationship does for your database, manually add an entry for smithc to your SurveyData table. (You will have to right click on the table and select Show Table Data. Close that window and save your changes when you are finished adding the row of data.) Then right click on the SurveyUsers table and select Show Table Data. Right click on the grey border in front of smithc and select Delete to try to delete this entry. Of course, you should not be allowed to do this, since smithc has related data in the other table. See this picture of what you get when SQL Server refuses to do the deletion.

Creating Home.aspx

  • The basic idea is to make your Home.aspx form look like this picture of the completed web form.
  • The 4 blue labels and the Login button are pretty obvious.
  • Change the ID of the text box next to the label "Login name:" to NameBox.
  • Change the ID of the text box next to the label "Password:" to PasswordBox.
  • Also change the TextMode property for this PasswordBox to Password. This causes this box to display asterisks when a user enters something into the box.
  • The items that look like red labels are all validators except for the one that says "Error in accessing database". That is an ordinary label. So, add that label and change its ID to ErrorLabel. Also change the Visible field to false. Our code will make this label visible if there is a database error.
  • To the right of NameBox add a required field validator. Change its ID to "NameRequiredFieldValidator" and fill in NameBox as the control to validate. Then fill in "Must supply a login name" in the ErrorMessage field under Properties. This validator will display its error message if the user fails to fill in a login name.
  • Similarly, to the right of PasswordBox add a required field validator. Change its ID to "PasswordRequiredFieldValidator" and fill in PasswordBox as the control to validate. Then fill in "Must supply a password" in the ErrorMessage field.
  • To the right of NameRequiredFieldValidator add a regular expression validator. Change its ID to something more meaningful if you wish and set NameBox as the control to validate. Fill in "Invalid login name" in the ErrorMessage field. We want this validator to display its message if the login name supplied by the user is too long or contains a character that we want to disallow.
  • To do this, click on the Validation Expression field and then click on the little button labeled with 3 dots. This brings up the regular expression editor. Although there are some pre-built regular expressions available here, we will type in our own. Put [a-zA-Z]{1,8} into the bottom field, the one labeled "Validation Expression" and click OK.
  • This regular expression allows any letters of the alphabet, upper or lower case. No other characters are allowed. In addition, the {1,8} specifies that there must be anywhere from 1 to 8 of these characters. Thus the login name cannot exceed 8 characters in length. This should keep malicious users from causing problems by sending data of very long length to your application.
  • To the right of PasswordRequiredFieldValidator add another regular expression validator. Change its ID if you wish and set PasswordBox as the control to validate. Fill in "Invalid password" in the ErrorMessage fields. We want this validator to display its message if the password supplied by the user is too long or contains a prohibited character.
  • To do this, click on the Validation Expression field and then click on the button with 3 the dots. Put [a-zA-Z0-9_+=]{1,8} into the bottom field of the regular expression editor, the field labeled "Validation Expression" and click OK.
  • This regular expression allows lower case letters (a through z), upper case letters (A through Z), digits (0 through 9), plus the underscore, plus sign, and equals sign. No other characters are allowed. In addition, the {1,8} specifies that there must be anywhere from 1 to 8 of these characters. Thus the password cannot exceed 8 characters in length.
  • Security tip 1: It is important to check at the server end for invalid data or data that is too long. Remember that an attacker has complete control of the client. VB .NET's validation controls do run at the server end (even if the EnableClientScript property of each validator is True so as to also do validation at the client end). The default seems to be that EnableClientScript is True, so that the validation runs at both ends. In most cases this seems to be reasonable. However, as you will see below, on the server end you must be careful that the validation is done before any critical code is run that processes the user's input.
  • Security tip 2: If security is of high importance, you would not want to report all of these helpful messages such as "Invalid login name" and "Invalid password". Instead, you would want to use one generic message so as not to make it any easier than necessary for an attacker to guess a correct username and password.
  • Finally add a custom validator below the 2 text boxes.
  • Change the ID of this validator to LoginCustomValidator and fill in PasswordBox as the control to validate. Use "Login failed" in the ErrorMessage field. Our plan is to have this message displayed if an incorrect password is submitted by the user. We will see how this is done later when we write the code-behind file for this page.
  • In Visual Studio do File, Save All.

It's Stored Procedure Time!

  • We need a stored procedure to look up the correct password for the login name supplied in NameBox.
  • We wish to use the same database connection string as before, the one that allows you to connect to your particular database. Since we made a new application, your Web.config file probably does not contain this connection string information. Simply use Notepad or Wordpad to open the Web.config file for one of your previous projects containing this string and then paste it into your Web.config file for the current project.
  • The result should be something like this:

<connectionStrings>
  <add name="PartsConnectionString" connectionString="Data Source=CIS-W2K8SERVER\SQL_CIS;Initial Catalog=CS305;Integrated Security=True"/>
</connectionStrings>

  • Save your modified Web.config file.
  • In Server Explorer, right click on the Stored Procedures folderi and select Add New Stored Procedure
  • .
  • In the resulting outline of a stored procedure put the name db_datareader.GetPassword after CREATE PROCEDURE.
  • Uncomment the parameter list and change it so that there is just one parameter, @Name nchar(8). This is the parameter in which you will pass in the username supplied by the person using the web app login page.
  • Put a blank line between SET NOCOUNT ON and RETURN. Right click there and select Design SQL Block to bring up the Query Builder.
  • Add the SurveyUsers table to the QueryBuilder grid.
  • Click the check box for the Password field and only then the box for the Username field. This is because we want the password to be the first column of data returned. In fact, we don't even need to return the username, but we do so just in case we might be able to use it in some revision of this program. (So, if you want to omit the username from the returned data, you could uncheck the Output entry for this field.)
  • In the Filter column of the Username row, place =@Name. This is to select the row of data that has the username matching what is sent in via the @Name parameter.
  • Note that the SQL in this Query Builder picture (the section that begins with "SELECT Password, Username") says that it is selecting first the Password field and then the Username, as we wished.
  • Do File, Save to save your work. Then run your stored procedure by right clicking on it and selecting Execute. In the resulting Run Stored Procedure window, fill in one of the valid login names (such as smithc) found in your SurveyUsers table. Then click on the OK button and verify that the correct password and username were returned.
  • Close the window containing the stored procedure code if you still have it open.

The Home.aspx.vb Code-Behind File

  • On the Home.aspx web form, double click on LoginCustomValidator, the one whose message reads "Login failed".
  • This will take you to the code-behind file, to an outline of a procedure to handle the validation.
  • The name of this procedure should be automatically set as LoginCustomValidator_ServerValidate.
  • We do not need to write any code for the Page_Load procedure.
  • However, we do need code for the LoginCustomValidator_ServerValidate procedure. This procedure will be executed when the user clicks on the Login button, thus causing a postback.
  • Insert the needed code so that it looks as follows:

Protected Sub LoginCustomValidator_ServerValidate(ByVal source As System.Object, _
    ByVal args As System.Web.UI.WebControls.ServerValidateEventArgs) _
    Handles LoginCustomValidator.ServerValidate

    Dim UserName, DatabasePassword As String
    Dim myDatabaseConnection As SqlClient.SqlConnection = Nothing
    Dim myCommand As SqlClient.SqlCommand = Nothing
    Dim myReader As SqlClient.SqlDataReader = Nothing

    Try
        ' Look up the username in the database, returning the corresponding password:
        Dim connectionString As String = _
            ConfigurationManager.ConnectionStrings("PartsConnectionString").ConnectionString
        myDatabaseConnection = New SqlClient.SqlConnection(connectionString)
        myCommand = New SqlClient.SqlCommand()

        UserName = NameBox.Text
        myCommand.CommandType = CommandType.StoredProcedure
        myCommand.Connection = myDatabaseConnection
        myCommand.Parameters.AddWithValue("@Name", UserName)
        myCommand.CommandText = "GetPassword"

        myDatabaseConnection.Open()
        myReader = myCommand.ExecuteReader

        If myReader.HasRows Then   ' The username was found.
            myReader.Read()
            DatabasePassword = myReader.GetString(0)
            myDatabaseConnection.Close()
            myDatabaseConnection.Dispose()
            If DatabasePassword = "" Then   ' This should not happen, but just in case...
                args.IsValid = False
            ElseIf DatabasePassword = args.Value Then
                args.IsValid = True
                FormsAuthentication.RedirectFromLoginPage(UserName, False)
            Else
                args.IsValid = False
            End If
        Else   ' The username was not found.
            args.IsValid = False
        End If
    Catch exception As System.Data.SqlClient.SqlException
        ErrorLabel.Visible = True
    Catch exception As Exception
        ErrorLabel.Visible = True
    Finally    'Do cleanup tasks here:
        myCommand = Nothing

        If Not myReader Is Nothing AndAlso _
            Not myReader.IsClosed Then
            myReader.Close()
        End If

        myReader = Nothing

        If Not myDatabaseConnection Is Nothing AndAlso _
            myDatabaseConnection.State = ConnectionState.Open Then
            myDatabaseConnection.Close()
            myDatabaseConnection.Dispose()
        End If

        myDatabaseConnection = Nothing
    End Try
End Sub

  • The main idea is to look up the correct password for the given username and see if it matches the password submitted by the user.
  • The code begins by setting up some variables.
  • We specify the database connection and set up a database command in our typical way.
  • Note that we get the username from the appropriate text box, the one with ID NameBox.
  • This username is then filled in as the value of the @Name parameter to our stored procedure.
  • Note, too, that we specify the GetPassword stored procedure as the one to be used in our database command.
  • We then use a data reader to process the results from the select command performed by the stored procedure.
  • Unlike the previous example, we expect only one row of data, not many. We should get just the row for the specified username.
  • Of course, if the user mistyped the login name, there might be no rows of data returned by the stored procedure. We check for this by looking at the HasRows property of the data reader.
  • If there was no data returned we set the result of this validation attempt to be false. This is done by placing False into args.IsValid.
  • On the other hand, if there is data, we read the line of data and then use GetString(0) to extract the first item from this row of data. (If your stored procedure returns the Username followed by the password, change this to GetString(1). The code above assumes that the password comes before the username.)
  • Although it should not occur, a check was made to see if the password returned is the empty string. If so, False is the answer to the validation attempt.
  • Otherwise, we check to see if the returned password matches the password submitted, here passed in via the args parameter (in args.Value) since PasswordBox was the control to validate.
  • If these match, the user should be logged in and redirected to the survey page. In FormsAuthentication this is done with a single line of code:
    FormsAuthentication.RedirectFromLoginPage(UserName, False)
  • You might wonder how the software knows what page to redirect to. This is automatically the page the user originally requested (if they got diverted to the login page) or the default page otherwise. This is why we name our survey page Default.aspx below.
  • Note that the second parameter of false indicates that the cookie used to give the user access should not be stored on the user's drive; it will exist only in main memory. This is exactly what we want for granting temporary access to the other web pages of this application.
  • More will be explained about FormsAuthentication below, but for the moment, let's finish the code.
  • Of course, if the passwords do not match, we put False into args.IsValid to indicate that the validation has failed. The custom validator on the web form will then display its error message.
  • If you wish to read more about the use of a custom validator, use Help, Search in Visual Studio to look for the topic "CustomValidator Class". You might also want to look up FormsAuthentication.
  • Save all of your files before going on.

FormsAuthentication

  • We already mentioned that FormsAuthentication uses a cookie to grant access to the other pages of the application.
  • The method of forms authentication requires some modifications to our Web.config file in Visual Studio.
  • Use Solution Explorer to open this file.
  • Modify this file so as to use the changes shown below:

<authentication mode="Forms">
   <forms loginUrl="Home.aspx" name=".ASPXFORMSAUTH">
   </forms>
</authentication>
<authorization>
   <deny users="?" />
</authorization>

  • Other sections of Web.config should remain as they were.
  • Note that the authentication mode is set to "Forms". This is how we specify that forms authentication is to be used.
  • The loginUrl is the page to direct the user to if an attempt is made to go directly to any other page of this application other than the login page. Of course, we make this to be Home.aspx, which is the login page! This is how we force the user to log in to get access.
  • The authorization section is set up to deny all users matching the ? wildcard. This means all unauthenticated users, all users who have not logged in. These users will not be able to reach any page in the application except for the login page, Home.aspx.
  • The authorization page can also be set to indicate who is allowed access. For example, the following would allow everyone access (by using the * wildcard for all users). This is the default setting.
    <allow users="*" />

Creating the Default.aspx Web Form

  • Add a new web form to your project. Recall that you can do this by right clicking on your project in Solution Explorer and then selecting Add, New Item, Web Form. Name your web form Default.aspx. Its task is to gather the survey data.
  • The final result for this web form should look like this picture of Default.aspx.
  • The "Confidential Employment Survey" label can be copied from Home.aspx.
  • Add the other blue labels and the 2 text boxes.
  • Change the ID of the label with text "Welcome" to WelcomeLabel, as we will need to refer to it later in our VB code.
  • Change the ID of the text box next to the label "Job Title" to JobTitleBox.
  • Change the ID of the text box next to the label "Salary" to SalaryBox.
  • Add the Submit button.
  • The items that look like red labels are validators.
  • We use these to be sure that the data entered into the text boxes is reasonable.
  • This is important both to assist the user and as a security measure to reduce the possibility of attacks that work by sending bad data to the web application and/or database.
  • To the right of JobTitleBox add the first regular expression validator. Change its ID if you wish. Fill in JobTitleBox as the control to validate. Then fill in "Use alphabetic characters" in the ErrorMessage field. We want this validator to display its message if the job title supplied by the user is too long or contains a character that we want to disallow.
  • To do this, click on the Validation Expression field and then click on the button labeled with 3 dots. This brings up the regular expression editor. Put [a-zA-Z\ ]{1,24} into the field labeled "Validation Expression" and click OK.
  • This regular expression allows lower and upper case letters and spaces. (The \ followed by a space indicates the space character.) The total length of the string must be anywhere from 1 to 24 characters. A string that is too long will be rejected. You can allow additional characters if you wish, though it is best not to allow a lot of special symbols as they are sometimes the basis for certain kinds of attacks.
  • Also add a required field validator for this same text box. For some reason the 1 in the 1,24 does not guarantee that the box has at least 1 character. The required field validator can handle that. Adjust it in the usual way.
  • To the right of SalaryBox add another regular expression validator. Change its ID if you wish and set SalaryBox as the control to validate. Fill in "Use an integer value" in the ErrorMessage field. We want this validator to display its message if the salary supplied by the user is too long or contains a prohibited character.
  • To do this, click on the Validation Expression field and then click on the button with 3 the dots. Put [0-9,]{1,12} into the "Validation Expression" field of the regular expression editor and click OK.
  • By now you should be able to interpret this regular expression. It allows digits (0 through 9), plus the comma (which might be used between groups of 3 digits). No other characters are allowed. In addition, the {1,12} specifies that there must be anywhere from 1 to 12 of these characters. Thus the salary number cannot exceed 12 characters in length. Note that we did not allow a decimal point, since whole numbers should be sufficient, nor did we allow a dollar sign.
  • Add a required field validator for this text box as well and adjust it in the usual way.
  • Save all of your files before proceeding further.

Another Stored Procedure

  • We need another stored procedure, this time to insert the user's job title and salary data into the SurveyData table.
  • In Server Explorer, right click on Stored Procedures and choose to make a new stored procedure.
  • This time we will not use Query Builder. Instead we will just write the code for the stored procedure. Make yours look like this:

CREATE PROCEDURE db_datareader.InsertSurveyData
    (
    @Username nchar(8),
    @Salary money,
    @Title nchar(24)
    )
AS
    INSERT INTO SurveyData (Username, Salary, Title)
    VALUES (@Username, @Salary, @Title)

  • Note that we pass in the Username, Salary, and Title as parameters to the stored procedure and that the stored procedure is named InsertSurveyData.
  • The types for the parameters have to match the types we used when we created the SurveyData table. You can always look this up in Server Explorer, in the tables section, by right clicking the table and selecting Open Table Definition.
  • Do File, Save to save your stored procedure. Then right click on it and select Execute. In the resulting Run Stored Procedure window fill in some data for an existing user and click OK.
  • After executing this code, the word CREATE gets changed to ALTER as usual. If you make a change and run this code again, you are altering an existing stored procedure.
  • Note that if you try to execute your stored procedure again with data for the same user, the database will refuse to accept this. That is because the username is the primary key in this table, so there cannot be 2 rows of data for the same username.
  • In Server Explorer, right click on your SurveyData file and select Show Table Data. Make sure that the data you just supplied was really inserted into the table. Then right click on the grey margin in front of that row and choose Delete to remove that row.

The Default.aspx.vb Code-Behind File

  • Open the Default.aspx.vb file.
  • Add the following code to the Page_Load procedure:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) _
    Handles Me.Load

    ' Add user name to the welcome label:
    WelcomeLabel.Text = WelcomeLabel.Text & " " & Context.User.Identity.Name
End Sub

  • You can see that we used the & symbol to append the username to the welcome message. With FormsAuthentication, Context.User.Identity.Name automatically contains the username for the logged in user.
  • Next, on the Default.aspx form, double click on the Submit button. This will place an outline of a SubmitButton_Click click handler into the VB file. Edit this procedure so that it looks like this:

Protected Sub SubmitButton_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles SubmitButton.Click

    Dim myDatabaseConnection As SqlClient.SqlConnection = Nothing
    Dim myCommand As SqlClient.SqlCommand = Nothing

    'Page.Validate()is called automatically before any click handler.
    If Page.IsValid Then
        Try
            ' Insert new row of data into the SurveyData table.
            Dim connectionString As String = _
                ConfigurationManager.ConnectionStrings("PartsConnectionString").ConnectionString
            myDatabaseConnection = New SqlClient.SqlConnection(connectionString)
            myCommand = New SqlClient.SqlCommand()

            myCommand.CommandType = CommandType.StoredProcedure
            myCommand.Connection = myDatabaseConnection
            myCommand.Parameters.AddWithValue("@Username", Context.User.Identity.Name)
            myCommand.Parameters.AddWithValue("@Salary", CInt(SalaryBox.Text))
            myCommand.Parameters.AddWithValue("@Title", JobTitleBox.Text)
            myCommand.CommandText = "InsertSurveyData"

            myDatabaseConnection.Open()
            myCommand.ExecuteNonQuery()
            myDatabaseConnection.Close()
            myDatabaseConnection.Dispose()
        Catch exception As System.Data.SqlClient.SqlException
            Response.Redirect("Failure.aspx")
        Catch exception As Exception
            Response.Redirect("Failure.aspx")
        Finally    'Do cleanup tasks here:
            myCommand = Nothing

            If Not myDatabaseConnection Is Nothing AndAlso _
                myDatabaseConnection.State = ConnectionState.Open Then
                myDatabaseConnection.Close()
                myDatabaseConnection.Dispose()
            End If

            myDatabaseConnection = Nothing
        End Try
        Response.Redirect("Success.aspx")
    End If
End Sub

  • The main goal here is to insert the user's data into the SurveyData table.
  • Since Page.Validate() is called after Page_Load, but before any click handlers, we know that the validators check the user data before the above SubmitButton_Click code runs. Thus we can check the page's IsValid property to see if everything is OK. If so, we go ahead and process the user's data. If not, we do nothing. The validator(s) on the page that detected a problem with the user data will display their text on the current page.
  • From here on let's assume that the user data validated as being reasonable.
  • We once again use Context.User.Identity.Name to look up the username and then place that value into the @Username parameter for our stored procedure.
  • We also get the data from SalaryBox. However, since we get it in string form, we have to convert it to a number. One way to do this is with the CInt function as shown. This function takes its parameter, a string, and returns the corresponding integer.
  • This integer salary is used as the value for the @Salary parameter to the same stored procedure.
  • Then the @Title parameter to the stored procedure is given the value taken from the text box for the job title.
  • The ExecuteNonQuery routine is used in order to execute the InsertSurveyData stored procedure. This is the first time we have used ExecuteNonQuery. (In the past we used ExecuteReader, as we were using a DataReader.)
  • If things work alright, we redirect the user to the Success.aspx page. Otherwise, we redirect the user to the Failure.aspx page. (Of course, we have not yet created these 2 pages.)
  • The most likely reasons that we would redirect to the failure page are that the application could not open the connection to the database or that the insertion failed (perhaps because there already is data in the SurveyData table for this user).
  • Notice that if an SqlException is not detected we go on to check to see if there is any exception whatsoever (as type Exception matches with any exception). This is just in case anything else might go wrong in the code in our Try block.
  • Since both Catch handlers execute the same code and the second one matches with all exceptions, the first Catch handler is redundant and could be removed. It is left in the code only in case we might want to modify things later so that different code is run for these 2 Catch handlers.
  • Save all of your files again.

The Success.aspx Web Form and Code-Behind File

  • Much like before, add a new web form to your project. Name it Success.aspx.
  • The purpose of this page is to tell the user that the data was recorded and to give the user the chance to log out.
  • Change the title of this form to "Employment Survey, Successful Data Submission".
  • Use this picture of Success.aspx as a guide.
  • As you can see, it simply contains 3 labels and a Logout button.
  • The first label can be copied from one of the previous 2 web forms.
  • Add the other labels and the button as well.
  • Change the ID of the button to LogoutButton.
  • Double click on the button to create a click handler for it in the Success.aspx.vb code-behind file. Then adjust the code to look like this:

Protected Sub LogoutButton_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles LogoutButton.Click

    FormsAuthentication.SignOut()
    Response.Redirect("Home.aspx")
End Sub

  • Note that all the code does is to call the SignOut function and then redirect the user to the login page, Home.aspx.
  • Save all of your files.

The Failure.aspx Web Form and Code-Behind File

  • Add another web form to your project. Name it Failure.aspx.
  • This page tells the user that there was some error which prevented the recording of the survey data. It also allows the user to log out.
  • Change the title of this form to "Employment Survey Failure to Record Data Page".
  • You can use this picture of Failure.aspx as a guide.
  • Add the 4 labels and the Logout button to the form.
  • Double click on the button to get the outline of a click handler in Failure.aspx.vb and change the code to match this:

Protected Sub LogoutButton_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles LogoutButton.Click

    FormsAuthentication.SignOut()
    Response.Redirect("Home.aspx")
End Sub

  • The code is identical to that used in the Success.aspx.vb code-behind file.
  • Save all of your files in Visual Studio.

Testing Your Web Application

  • Build your project in the usual manner.
  • Fix any errors that are noted and build again as needed.
  • Use Debug, Start Without Debugging to run your app locally on your PC.
  • Test your application with normal data. That is, try to login with a username and password from your SurveyUsers table. Assuming that this works, fill in a job title and salary and see if submitting this data results in the data being correctly inserted into the SurveyData table. (Remember that in Server Explorere you can see a table's data by right clicking on it and then selecting Show Table Data.)
  • We assume that the SurveyData table will be viewed in SQL Server by the database administrator or by writing another application (not shown here) to view or process the data.
  • Next, try to log in again as the same user that just successfully submitted some data. You should be able to log in, but the application should give you the failure page when you try to submit data. (This is because the database refuses to allow 2 entries with the same username, as the username field is the primary key for the SurveyData table.)
  • Then after successfully logging in, submitting some survey data, and logging out, use the back button to go back to the survey page and click Submit again. The application should send you to the login page as you were not logged in.
  • Try various combinations of invalid usernames and passwords at the login page to be sure that the validators are working correctly.
  • Also try invalid data on the survey page, such as a job title with numbers in it or a salary value that is too long. This will check out that page's validators.
  • Note that you might get somewhat different behaviors depending on the user's browser, the browser's security settings (such as whether it will run client-side script), and whether you have the EnableClientScript property set to True for the validators (which it seems to be by default). If client-side script is not used, then you might see a delay before an error message appears due to the round-trip to the server to process the user's bad input.

Using the Secure Web Server

  • Publish your web app to a real web server and have the web server administrator mark it as an official IIS web app.
  • Then view this copy of the web app in a browser to be certain that everything works.
  • Better security can and should be provided by using the secure web server.
  • This, too, will require the assistance of your web server administrator.
  • Ask this person to require secure access to this application.
  • Although this must be done by the web server administrator, for completeness, here are the steps needed:
    • In Internet Information Services (IIS) Manager on the server, find the user's web folder and the particular project within, the one that was just made an IIS web app.
    • Click on the web app folder and then double click on the SSL Settings icon.
    • Check the box labeled "Require SSL" and (for stronger encryption) check the "Require 128-bit SSL" box as well.
    • Under Actions, click on Apply.
  • This requires the use of SSL to encrypt any data flowing between the user's browser and the web server. In addition, it allows the user to view and accept the server's certificate.
  • This certificate's purpose is to verify that this server is the web server it purports to be.
  • Now if you try to view your web app using the usual URL, such as:
    http://cis2.stvincent.edu/studentc/Login/Home.aspx
    you get an error message saying that you must use SSL. Here is a picture of the error message produced.
  • To access your web app you must now use https instead of http at the start of the URL, like this:
    https://cis2.stvincent.edu/studentc/Survey/home.aspx
  • The use of https gives you both encryption of data and access to the web server's certificate.
  • Normally this certificate would be signed by a recognized certificate authority. If not, or if the certificate has expired, your browser should warn you. When using our own certificate (not one signed by a certificate authority), we got this invalid certificate, issuer unknown message when using Firefox, for example. A properly signed certificate indicates to the user that this web server is the web server it says that it is. Otherwise, the user has no guarantee about the identity of this server. Our certificate is self-signed (which provides no guarantee unless you trust us), but a commercial website would use a certificate signed by a known certificate authority. Modern browers would accept this type of signed certificate automatically, as they contain in their settings a list of acceptable certificate authorities. A site whose certificate is not signed by a recognized authority is likely either malicious or is run by an educational institution, not a commerical enterprise.
  • Firefox lets us allow the site (given by our self-signed certificate) as an exception. Only do this if you are sure you can trust the site.
  • Once the certificate is accepted, you can view the Home.aspx login page. In Firefox or Internet Explorer note that the URL begins with https and that there is a padlock icon on the browser. In Internet Explorer, the user can click on this padlock, which gives this Website Identification window. Click on its View Certificates link to examine the server's certificate. In Firefox, you double click on the padlock to view the certificate information.

Summary

  • This web application does a lot more than our previous examples.
  • It illustrates many useful features, such as how to password-protect a web application using a login/logout process and how to insert data into a table from within a web app. We also examined the use of secure communications (encryption of data and the web server certificate).
  • Note that we only learned to use one particular method of authenticating users. There are a number of other methods available.
  • Although real-world web apps are often much more complex, this example begins to show some of the functionality needed in these larger applications, such as e-commerce applications.
  • Suggestion: Now that you know how a web app can both get data from a database and write data to one, develop a guestbook web application that allows users to submit data and view previous submissions. Be careful to validate the user data for the sake of security. (.NET web apps supposedly automatically filter out scripts, thus preventing cross-site scripting attacks in which a user submits a malicious script instead of the expected type of guestbook data. That script can then run on a victim user's computer when the victim views the guestbook entries. Nevertheless, adding validators to be sure that you get only acceptable data makes things safer.)

Back to the main page for ASP .NET Web Apps



Author: Br. David Carlson
Last updated: November 17, 2008
Disclaimer