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(…)
Server-Side
Includes for Navigation - WOW This may be old news to a lot
of you, but I had never heard of it until a couple of months ago. Someone showed
me how to implement server side includes in my HMTL documents – in particular
how to use them for easily updateable navigation. You set up your pages as .SHTML
instead of .HTML pages and the use an include in your text such as...
Read Replies
|
|
|
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";
}
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.
Article first appeared at ASP101
About the Author:
I'm currently lead developer at DATA, Inc. (www.datausa.com)
a digital visualization company specializing in 3D-computer animation and high
end web application development. I have worked in several different languages
including VC++, VisualBasic, ASP.NET, C#. In my spare time I write articles about
my experiences hoping they will help someone else out.
Read this newsletter at: http://www.webproasp.com/2003/0829.html |
|