用户在管理帐户或进行购买前,他或她必须使用熟悉的登录过程登录到 Duwamish 7.0。“Logon”(登录)页使用 ASP.NET 基于窗体的身份验证来验证用户是否提供了唯一的电子邮件别名和密码。尚未建立帐户的用户可以通过单击“New Customer”(新建客户)按钮创建一个帐户。有关创建新帐户的详细信息,请参见帐户管理。
实现
“Logon”(登录)页使用下面的 ASP.NET 文件和 C# 或 Visual Basic .NET 代码隐藏文件:
Logon.aspx
Logon.aspx.cs
Logon.aspx.vb
注意 有关 ASP.NET 代码隐藏的更多信息,请参见创建 ASP.NET Web 应用程序。
过程概述
在 Web 层中启动登录过程。用户输入电子邮件地址和密码(凭据),然后单击“Logon”(登录)按钮,这将调用 Duwamish7.Web.Logon.LogonButton_Click 方法。下一步,Duwamish7.Web.Logon.LogonButton_Click 方法创建密码的散列表示形式,并将凭据传递给业务外观层的 Duwamish7.BusinessFacade.CustomerSystem.GetCustomerByEmail 方法。接着 Duwamish7.DataAccess.Customers.LoadCustomerByEmail 方法调用数据访问层,后者又调用 GetCustomerByEmail 存储过程 (SPROC)。然后通过 ComparePasswords 方法,相对于从数据库中检索的经过 salt 和散列运算的密码来验证散列密码。如果凭据有效,则客户帐户信息成功地存储到 Cart 对象,并且 ASP.NET Forms 身份验证通过 pageBase 类 ShoppingCart.Customer() 属性验证凭据。如果凭据无效,则 MismatchLabel 设置为可见,它在 ASP.NET 页上显示下面的内容:“Invalid email address or password- please try again”(电子邮件地址或密码无效,请再试一次)。
注意 有关对密码进行 salt 和散列运算的进一步信息,请参见密码凭据保护。
若要查找适用于本主题中特定层的源代码,请单击相应的链接:
业务外观源代码 | 数据访问源代码 | SPROC
Web 源代码
Duwamish7.Web.Logon.LogonButton_Click 方法源代码的默认位置是 [安装 Visual Studio .NET 的驱动器号]:/Program Files/Microsoft Visual Studio .NET 2003/Enterprise Samples/Duwamish 7.0 CS/Web/Secure/Logon.aspx.cs 文件。
注意 如果安装了 Visual Basic .NET 版本,则 Duwamish 7.0 VB 将替换路径中的 Duwamish 7.0 CS,其文件名相同,但扩展名是 vb 而不是 cs。
Duwamish7.Web.Logon.LogonButton_Click 方法:
[C#]
/// <summary>
/// Validates a logon attempt saves off the customer account information.
/// <param name="sender">The source of the event.</param>
/// <param name="e">An EventArgs that contains the event data.</param>
/// </summary>
public void LogonButton_Click(Object sender, EventArgs e)
{
CustomerData custData;
//
// Check the Email and Password
//
MismatchLabel.Visible = false;
//Validator controls make sure Email and Password exist
if (!Page.IsValid)
{
return;
}
//
// Check for already logged on
//
if (logonCustomerData != null)
{
ShowPanel(LogonPanel, false);
ShowPanel(DetailsPanel, false);
ShowPanel(CreatedPanel, false);
ShowPanel(LoggedOnPanel, true);
ViewState["target"] = "logon";
return;
}
//
// Ensure the right panel == visible
//
ShowPanel(LogonPanel, true);
ShowPanel(LoggedOnPanel, false);
ShowPanel(DetailsPanel, false);
ShowPanel(CreatedPanel, false);
//
// Check the Email and Password combination
//
SHA1 sha1 = SHA1.Create();
byte [] password = sha1.ComputeHash(Encoding.Unicode.GetBytes(LogonPasswordTextBox.Text));
custData = (new CustomerSystem()).GetCustomerByEmail(LogonEmailTextBox.Text, password);
if (custData != null) //were they valid?
{
//
// 1. Update customer in session.
// 2. Update customer in cart.
//
base.Customer = custData;
base.ShoppingCart().Customer = custData;
FormsAuthentication.RedirectFromLoginPage("*", false);
}
else
{
MismatchLabel.Visible = true;
}
}
[Visual Basic .NET]
'----------------------------------------------------------------
' Sub LogonButton_Click:
' Validates a logon attempt then saves off the customer account information.
' Parameters:
' [in] sender: Standard onlcick parameter for the sending object
' [in] e: Standard click parameter for the event arguments
'----------------------------------------------------------------
Private Sub LogonButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Dim custData As CustomerData
'
' Check the Email and Password
'
MismatchLabel.Visible = False
'
'Validator controls make sure Email and Password exist
'
If Not Page.IsValid Then
Return
End If
'
' Check for already logged on
'
If Not logonCustomerData Is Nothing Then
ShowPanel(LogonPanel, False)
ShowPanel(DetailsPanel, False)
ShowPanel(CreatedPanel, False)
ShowPanel(LoggedOnPanel, True)
Me.ViewState("target") = "logon"
Exit Sub
End If
'
' Ensure the right panel is visible
'
ShowPanel(LogonPanel, True)
ShowPanel(LoggedOnPanel, False)
ShowPanel(DetailsPanel, False)
ShowPanel(CreatedPanel, False)
'
' Check the Email and Password combination
'
With New CustomerSystem()
' <A href=viewsource.aspx?Title=CustomerSystem.vb&FilePath=../Business/Facade/CustomerSystem.vb>CustomerSystem.GetCustomerByEmail()</A>
Dim sha1 As SHA1 = SHA1.Create()
Dim password As byte() = sha1.ComputeHash(Encoding.Unicode.GetBytes(LogonPasswordTextBox.Text))
custData = .GetCustomerByEmail(LogonEmailTextBox.Text, password)
End With
If Not custData Is Nothing Then 'were they valid?
'
' 1. Update customer in session.
' 2. Update customer in cart.
'
MyBase.Customer = custData
MyBase.ShoppingCart.Customer = custData
FormsAuthentication.RedirectFromLoginPage("*",false)
Else
MismatchLabel.Visible = True
End If
End Sub
业务外观源代码
Duwamish7.BusinessFacade.CustomerSystem.GetCustomerByEmail 方法源代码的默认位置是 [安装 Visual Studio .NET 的驱动器号]:/Program Files/Microsoft Visual Studio .NET 2003/Enterprise Samples/Duwamish 7.0 CS/Business/Facade/CustomerSystem.cs 文件。
注意 如果安装了 Visual Basic .NET 版本,则 Duwamish 7.0 VB 将替换路径中的 Duwamish 7.0 CS,其文件名相同,但扩展名是 vb 而不是 cs。
Duwamish7.BusinessFacade.CustomerSystem.GetCustomerByEmail 方法:
[C#]
/// <summary>
/// Retrieve a customer given the customer's email and password.
/// <param name="emailAddress">Customer's email address.</param>
/// <param name="password">Customer's account password.</param>
/// <retvalue>The customer or null.</retvalue>
/// <exception> class='System.ApplicationException'>
/// The emailAddress or password is blank.
/// </exception>
/// </summary>
public CustomerData GetCustomerByEmail(String emailAddress, byte [] password)
{
//
// Check preconditions
//
ApplicationAssert.CheckCondition(emailAddress != String.Empty, "Email address is required", ApplicationAssert.LineNumber);
ApplicationAssert.CheckCondition(password.Length != 0, "Password is required", ApplicationAssert.LineNumber);
//
// Get the customer dataSet
//
CustomerData dataSet;
using (DataAccess.Customers customersDataAccess = new DataAccess.Customers())
{
dataSet = customersDataAccess.LoadCustomerByEmail(emailAddress);
}
//
// Verify the customer's password
//
DataRowCollection rows = dataSet.Tables[CustomerData.CUSTOMERS_TABLE].Rows;
if ( ( rows.Count == 1 ))
{
byte [] dbPassword = (byte[])rows[0][CustomerData.PASSWORD_FIELD];
if (ComparePasswords (dbPassword, password))
return dataSet;
else
return null;
}
else
return null;
[Visual Basic .NET]
'----------------------------------------------------------------
' Function GetCustomerByEmail:
' Retrieve a customer given the customer's email and password.
' Returns:
' The customer or Nothing
' Parameters:
' [in] emailAddress: Customer's email address
' [in] password: Customer's account password
' Throws:
' PreConditionException
' PreConditions:
' emailAddress or password is blank
'----------------------------------------------------------------
Public Function GetCustomerByEmail(ByVal emailAddress As String, ByVal password As byte()) As CustomerData
'
' Check preconditions
'
ApplicationAssert.CheckCondition( Len(emailAddress) > 0, "Email address is required", ApplicationAssert.LineNumber)
ApplicationAssert.CheckCondition( password.Length > 0, "Password is required", ApplicationAssert.LineNumber)
Dim dataSet As CustomerData ' used manipulate CustomerData
'
' Get the customer dataSet
'
With New DataAccess.Customers
dataSet = .LoadCustomerByEmail(emailAddress)
End With
'
' Verify the customer's password
'
With dataSet.Tables(CustomerData.CUSTOMERS_TABLE).Rows
If (.Count = 1) Then
Dim dbPassword As byte()
dbPassword = CType(.Item(0).Item(CustomerData.PASSWORD_FIELD), byte())
If (ComparePasswords(dbPassword, password)) Then
GetCustomerByEmail = dataSet
End If
End If
End With
End Function
数据访问源代码
Duwamish7.DataAccess.Customers.LoadCustomerByEmail 方法源代码的默认位置是 [安装 Visual Studio .NET 的驱动器号]:/Program Files/Microsoft Visual Studio .NET 2003/Enterprise Samples/Duwamish 7.0 CS/DataAccess/Customers.cs 文件。
注意 如果安装了 Visual Basic .NET 版本,则 Duwamish 7.0 VB 将替换路径中的 Duwamish 7.0 CS,其文件名相同,但扩展名是 vb 而不是 cs。
Duwamish7.DataAccess.Customers.LoadCustomerByEmail 方法:
[C#]
/// <summary>
/// Retrieves the customer with the provided email address.
/// <param name="emailAddress">Email address for customer.</param>
/// <retvalue>CustomerData, a dataset containing detailed customer information.</retvalue>
/// </summary>
public CustomerData LoadCustomerByEmail(String emailAddress)
{
if ( dsCommand == null )
{
throw new System.ObjectDisposedException( GetType().FullName );
}
CustomerData data = new CustomerData();
//
// Get the load command
//
dsCommand.SelectCommand = GetLoadCommand();
dsCommand.SelectCommand.Parameters[EMAIL_PARM].Value = emailAddress;
dsCommand.Fill(data);
//
// Check post conditions
//
ApplicationAssert.CheckCondition(data.Tables[CustomerData.CUSTOMERS_TABLE].Rows.Count <= 1, "Integrity Failure: non-unique e-mail address", ApplicationAssert.LineNumber);
return data;
}
[Visual Basic .NET]
'----------------------------------------------------------------
' Function LoadCustomerByEmail:
' Retrieves the customer with the provided email address.
' Returns:
' CustomerData, a dataset containing detailed customer information.
' Parameters:
' [in] emailAddress: Email address for customer
'----------------------------------------------------------------
Public Function LoadCustomerByEmail(ByVal emailAddress As String) As CustomerData
Dim data As New CustomerData
With dsCommand
Try
.SelectCommand = GetLoadCommand
.SelectCommand.Parameters(EMAIL_PARM).Value = emailAddress
.Fill(data)
Finally
If Not .SelectCommand Is Nothing Then
If Not .SelectCommand.Connection Is Nothing Then
.SelectCommand.Connection.Dispose()
End If
.SelectCommand.Dispose()
End If
.Dispose()
End Try
End With
'
' Check post conditions
'
ApplicationAssert.CheckCondition(data.Tables(CustomerData.CUSTOMERS_TABLE).Rows.Count <= 1, "Integrity Failure: non-unique e-mail address", ApplicationAssert.LineNumber)
LoadCustomerByEmail = data
End Function
SPROC
SQL 存储过程的默认位置是 [安装 Visual Studio .NET 的驱动器号]:/Program Files/Microsoft Visual Studio .NET 2003/Enterprise Samples/Duwamish 7.0 CS/Database/SQLScripts/D7_Sprocs.sql 文件。
注意 如果安装了 Visual Basic .NET 版本,则 Duwamish 7.0 VB 将替换路径中的 Duwamish 7.0 CS。
--------------------------------------------------
-- GetCustomerByEmail
--------------------------------------------------
CREATE PROCEDURE GetCustomerByEmail
@Email NVARCHAR(50) = NULL
AS
SET NOCOUNT ON
SELECT c.PKId,
c.Email,
c.Password,
c.Name,
a.Address,
a.Country,
a.PhoneNumber,
a.Fax
FROM Customers c,
Addresses a
WHERE c.Email = @Email
AND a.CustomerId = c.PKId
RETURN 0