ASP 101 - Active Server Pages 101 - Web06
The Place ASP Developers Go!

Please visit our partners


Windows Technology Windows Technology
15 Seconds
4GuysFromRolla.com
ASP 101
ASP Wire
VB Forums
VB Wire
WinDrivers.com
internet.commerce internet.commerce
Partners & Affiliates














ASP 101 is an
internet.com site
ASP 101 is an internet.com site
IT
Developer
Internet News
Small Business
Personal Technology

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers

ASP 101 News Flash ASP 101 News Flash



 Top ASP 101 Stories Top ASP 101 Stories
Connections, Commands, And Procedures
What is ASP?
VBScript Classes: Part 1 of N

QUICK TIP:
Upgrade to the 5.5 Scripting Engine
Show All Tips >>
ASP 101 RSS Feed ASP 101 Updates


Using ASP.NET to Make a Secure Site and Move Login Processing Out of the Page

by Matt Rutledge

A lot of us are tasked everyday to come up with ways of making our site, and other sites secure. Well if you're anything like me you don't want to have to rewrite login code 20 times a day. I'm going to show you how to make a secure site and have the login processing in a separate class. Let's get started.

In .NET to make a site secure is very simple, open up Web.Config file and look for the line that says <authentication mode="Windows" />. Delete that line and put in the following:

<authentication mode="Forms">
  <forms name="yourAuthCookie" loginUrl="login.aspx"
    protection="All" path="/" />
</authentication>
<authorization>
  <deny users="?" />
</authorization>

This now changes the way your web application will authenticate, it will no longer use NT security. Anybody trying to hit a page without authenticating first will be bounced back to the loginUrl that is specified.

Now I know a lot of you are thinking, but I have pages that aren't secure that I want the user to see. Well that is easy. After the <system.web> tag in your Web.Config file has ended put the following:

  <location path="test.aspx">
    <system.web>
      <authorization>
        <allow users="?" />
      </authorization>
    </system.web>
  </location>

This will allow any user, authenticated or not, to access that page only, if you have a whole directory you want anyone to access just put the directory name in the path, and I mean just the name no slashes or wildcards.

Now that we have a secure site we need to make the login page that we specified in the loginUrl.

Just a quick note, I am going to be using C# in this example with a SQL database and I will supply a code sample.

Start off by creating a webform and put your form fields in there. Use web controls for your fields not HTML controls.

<%@ Page language="c#" Codebehind="login.aspx.cs"
  AutoEventWireup="false" Inherits="secure.login" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
  <HEAD>
    <title>Secure Site</title>
    <meta content="Microsoft Visual Studio 7.0" name="GENERATOR">
    <meta content="C#" name="CODE_LANGUAGE">
    <meta content="JavaScript" name="vs_defaultClientScript">
    <meta content="http://schemas.microsoft.com/intellisense/ie5"
      name="vs_targetSchema">
  </HEAD>
  <body MS_POSITIONING="GridLayout">
    <form id="login" method="post" runat="server">
      <table cellSpacing="0" cellPadding="0" border="0">
      <tr>
        <td vAlign="top" align="left">
          <asp:label id="Message" Runat="server" ForeColor="#ff0000">
          </asp:label>
        </td>
      </tr>
      <tr>
        <td vAlign="top" align="left">
          <b>E-mail:</b>
        </td>
      </tr>
      <tr>
        <td vAlign="top" align="left">
          <asp:textbox id="username" Runat="server" Width="120">
          </asp:textbox>
        </td>
      </tr>
      <tr>
        <td vAlign="top" align="left">
          <b>Password:</b>
        </td>
      </tr>
      <tr>
        <td vAlign="top" align="left">
          <asp:textbox id="password" Runat="server"
            Width="120" TextMode="Password">
          </asp:textbox>
        </td>
      </tr>
      <tr>
        <td vAlign="top" align="left">
          <asp:checkbox id="saveLogin" Runat="server"
            Text="<b>Save my login</b>">
          </asp:checkbox>
        </td>
      </tr>
      <tr>
        <td vAlign="top" align="right">
          <asp:imagebutton id="btnLogin" Runat="server"
            ImageUrl="/images/w2k/login/btnLogin.gif">
          </asp:imagebutton>
        </td>
      </tr>
      </table>
    </form>
  </body>
</HTML>

Now in the code behind page create a click event for the login button.

private void InitializeComponent()
{    
  this.btnLogin.Click += new System.Web.UI.ImageClickEventHandler(this.btnLogin_Click);
  .
  .
  .
}

and put the function in.

    private void btnLogin_Click(object sender, System.Web.UI.ImageClickEventArgs e)
    {
      CCommonDB sql = new CCommonDB();
      string redirect = "";
      if((redirect = sql.AuthenticateUser(this.Session, this.Response,
        username.Text, password.Text, saveLogin.Checked)) != string.Empty)
      {
        // Redirect the user
        Response.Redirect(redirect);
      }
      else
      {
        Message.Text = "Login Failed!";
      }
    }

In this example I am actually returning a specified redirect, but if you would like to redirect them to the page that they came from you can always use: FormsAuthentication.RedirectFromLoginPage(…)

Here is the CCommonDB class that I use to authenticate users.

CCommonDB.cs
namespace secure.Components
{
  public class CCommonDB : CSql
  {
    public CCommonDB() : base() { }
    public string AuthenticateUser(
      System.Web.SessionState.HttpSessionState objSession, // Session Variable
      System.Web.HttpResponse objResponse,                 // Response Variable
      string email,                                        // Login
      string password,                                     // Password
      bool bPersist                                        // Persist login
      )
    {
      int nLoginID  = 0;
      int nLoginType  = 0;
      // Log the user in
      Login(email, password, ref nLoginID, ref nLoginType);
      if(nLoginID != 0)  // Success
      {
        // Log the user in
        System.Web.Security.FormsAuthentication.SetAuthCookie(nLoginID.ToString(), bPersist);
        // Set the session varaibles    
        objSession["loginID"]  = nLoginID.ToString();
        objSession["loginType"] = nLoginType.ToString();
        // Set cookie information incase they made it persistant
        System.Web.HttpCookie wrapperCookie = new System.Web.HttpCookie("wrapper");
        wrapperCookie.Value = objSession["wrapper"].ToString();
        wrapperCookie.Expires = DateTime.Now.AddDays(30);
        System.Web.HttpCookie lgnTypeCookie = new System.Web.HttpCookie("loginType");
        lgnTypeCookie.Value = objSession["loginType"].ToString();
        lgnTypeCookie.Expires = DateTime.Now.AddDays(30);
        // Add the cookie to the response
        objResponse.Cookies.Add(wrapperCookie);
        objResponse.Cookies.Add(lgnTypeCookie);
        return "/candidate/default.aspx";
          }
          case 1:  // Admin Login
          {
            return "/admin/default.aspx";
          }
          case 2:  // Reporting Login
          {
            return "/reports/default.aspx";
          }
          default:
          {
            return string.Empty;
          }
        }
      }
      else
      {
        return string.Empty;
      }
    }
    /// <summary>
    /// Verifies the login and password that were given
    /// </summary>
    /// <param name="email">the login</param>
    /// <param name="password">the password</param>
    /// <param name="nLoginID">returns the login id</param>
    /// <param name="nLoginType">returns the login type</param>
    public void Login(string email, string password, ref int nLoginID, ref int nLoginType)
    {
      ResetSql();
      DataSet ds = new DataSet();
      // Set our parameters
      SqlParameter paramLogin = new SqlParameter("@username", SqlDbType.VarChar, 100);
      paramLogin.Value = email;
      SqlParameter paramPassword = new SqlParameter("@password", SqlDbType.VarChar, 20);
      paramPassword.Value = password;
      Command.CommandType = CommandType.StoredProcedure;
      Command.CommandText = "glbl_Login";
      Command.Parameters.Add(paramLogin);
      Command.Parameters.Add(paramPassword);
      Adapter.TableMappings.Add("Table", "Login");
      Adapter.SelectCommand = Command;
      Adapter.Fill(ds);
      if(ds.Tables.Count != 0)
      {
        DataRow row = ds.Tables[0].Rows[0];
        // Get the login id and the login type
        nLoginID  = Convert.ToInt32(row["Login_ID"].ToString());
        nLoginType  = Convert.ToInt32(row["Login_Type"].ToString());
      }
      else
      {
        nLoginID = 0;
        nLoginType = 0;
      }
    }
  }
  abstract public class CSql
  {
    private SqlConnection sqlConnection;      // Connection string
    private SqlCommand sqlCommand;          // Command
    private SqlDataAdapter sqlDataAdapter;      // Data Adapter      
    private DataSet sqlDataSet;            // Data Set
    public CSql()
    {
      sqlConnection  = new SqlConnection(ConfigurationSettings.AppSettings["ConnectionString"]);
      sqlCommand    = new SqlCommand();
      sqlDataAdapter  = new SqlDataAdapter();
      sqlDataSet    = new DataSet();
      sqlCommand.Connection = sqlConnection;
    }
    /// <summary>
    /// Access to our sql command
    /// </summary>
    protected SqlCommand Command
    {
      get { return sqlCommand; }
    }
    /// <summary>
    /// Access to our data adapter
    /// </summary>
    protected SqlDataAdapter Adapter
    {
      get { return sqlDataAdapter; }
    }
    /// <summary>
    /// Makes sure that everything is clear and ready for a new query
    /// </summary>
    protected void ResetSql()
    {
      if(sqlCommand != null)
      {
        sqlCommand = new SqlCommand();
        sqlCommand.Connection = sqlConnection;
      }
      if(sqlDataAdapter != null)
        sqlDataAdapter = new SqlDataAdapter();
      if(sqlDataSet != null)
        sqlDataSet = new DataSet();
    }
    /// <summary>
    /// Runs our command and returns the dataset
    /// </summary>
    /// <returns>the data set</returns>
    protected DataSet RunQuery()
    {
      sqlDataAdapter.SelectCommand = Command;
      sqlConnection.Open();
      sqlConnection.Close();
      sqlDataAdapter.Fill(sqlDataSet);
      return sqlDataSet;
    }
  }
}

I have two classes here, a base class for the common sql functions that most of use normally do and then a class that inherits from that class to separate the code.

When you look at the code you may ask why do you pass the session variable and response variable into the function, well if you have ever tried to access the Session or Response variable from a separate cs class you always get an error saying that you need reference to the object, and in this case you can just pass the objects in and out easily and quickly without having to try to create your own instance of the Session or Response.

If you have questions please feel free to write me at ruts@datausa.com and I'll answer them the best I can.

Matt Rutledge
ruts@datausa.com
www.datausa.com


Home |  News |  Samples |  Articles |  Lessons |  Resources |  Forum |  Links |  Search |  Feedback

Internet.com
The Network for Technology Professionals

Search:

About Internet.com

Legal Notices, Licensing, Permissions, Privacy Policy.
Advertise | Newsletters | E-mail Offers