http://www.cnblogs.com/shineqiujuan/archive/2008/05/03/1180612.html
通過上一部分的學習,我們已知道:Cookie是ASP中的一個對象集合,它以加密的形式被保存在客戶端特定文件夾內,用戶可以修改、刪除甚至僞造Cookie;而Session是一個服務器對象,它被保存在服務器,所以相對地,使用Session較爲安全,但較耗費服務器資源。你可以隨意設置Cookie的生存期,例如1年。但如果你讓一個Session變量始終生存在服務器主機內,對你的服務器來說並不是一個好的選擇,通常來講,涉及到“管理權限”的時候纔會用Cookie+Session雙認證。
首先我們還是在ASP.NET中練習寫入和讀取Cookie和Session,瞭解一些Cookie的基本知識:Cookie對象是.NET Framework中HttpCookie類實例化的模型。下面我們來學習ASP.NET中與Cookie密切相關的一些方法:
1. 如何建立Cookie:ASP.NET建立Cookie的標準代碼寫法是
HttpCookie myCookie = new HttpCookie("someCookie");
這句代碼建立了一個名爲myCookie的Cookie對象
2. 接收Cookie對象:接收ASP.NETCookie對象的標準代碼寫法是
HttpCookie getCookie = Request.Cookies["someCookie"];
設置getCookie爲一個Cookie對象,它是請求頁面中Cookie對象數組中someCookie的子集。如果名爲someCookie的Cookie數組不存在,則getCookie的null屬性爲true。
3. 給Cookie增加鍵值:ASP.NET增加鍵值的標準代碼寫法是
myCookie.Values.Add("auth", "admin");
給名爲myCookie的Cookie對象(必須實現建好)增加一個auth鍵名,其值爲admin。
4. 附加鍵值,使Cookie生效:標準代碼格式爲
Response.Cookies.Add(myCookie);
上句代碼把名爲myCookie的對象附加到Cookie數組內。注意,在設定Cookie完畢之後一定要加上這句代碼才能生效,
4. 設定生存期:設置生存期的標準代碼形式如下
myCookie.Expires = DateTime.Now.AddDays(3);
設定名爲myCookie的Cookie對象生存期爲當前時間加上3天。需要注意的是,設定Cookie之後如果頁面不刷新,是不會顯示任何效果的。
5. 獲取Cookie的值:獲取Cookie值的標準代碼格式爲
myCookie.Values["auth"];
上句代碼可以獲取名爲myCookie的Cookie對象鍵名爲auth的鍵值。如果不存在,則返回null。
10.3.2 ASP.NET中練習使用Cookie
在Visual Studio 2005“解決方案資源管理器”內的地球圖標點右鍵→“添加新項”,在彈出的窗口中把文件名命名爲Cookie.aspx,按“確定”按鈕,片刻之後,“解決方案資源管理器”裏便出現了新添加的頁面文件Cookie.aspx和邏輯文件Cookie.cs。我們首先在HTML狀態下弄懂ASP.NET Cookie的使用方法,只要原理弄懂,在Flash RIA工程中只要使輸出文檔類型由HTML變爲XML就萬事大吉了。
爲了增加讀者的實際動手能力,我們在示例中選用了一個廣爲人知“BBS登錄系統”,相信所有泡過BBS論壇的朋友對此都不陌生
圖10.37所示爲國內Flash門戶網站“閃吧 http://www.flash8.net/”的登錄系統,這個登錄系統主要包含幾個部分:“用戶名、密碼”輸入框、“有效期”下拉菜單,“登錄”按鈕。上述一切都被包含到一個表單標籤中,一旦“登錄”按鈕被按下,輸入框和下拉菜單中的值就會以POST的方式提交給後臺頁面加以驗證。
圖10.37
我們爲了模擬這種效果,需要在Visual Studio 2005的“工具箱”中向工作區拖入一個Panel組件(ID命名爲myPanel)、兩個TextBox組件(ID分別命名爲myUID和myPWD)、一個Button組件(ID命名爲myBTN)、一個DropDownList組件(ID命名爲myDDL)和一個LinkButton組件(ID命名爲myLB)。並且我們需要把 除LinkButton以外的其他組件都拖入Panel內。Panel是“羣組”組件,其他組件一旦被拖入Panel組件,我們就可以通過控制Panel組件統一管理被它包含的組件。例如,在本例中只需寫一句 myPanel.Visible = false;就可以讓所有包含在myPanel組件中的所有組件不可見。在myUID和myPWD組件的前面分別添加提示文字:“用戶名”和“密 碼”;在myLB的“屬性窗口”中添加它的Text屬性爲“退出系統”;單擊myDDL組件,在右側“屬性窗口”裏找到“雜項”→Items表格,單擊(collection)右側的“...”按鈕,爲myDDL下拉菜單綁定數據源(這和Flash裏的ComboBox很像),如圖10.38所示:
圖10.38
在彈出的窗口,按圖10.39所示填寫:
圖10.39
其中我們可以通過“添加”一個選項、每個選項都右4個屬性Enabled(是否可以選擇)、Selected(是否默認就處於“被選中”狀態。注意:最多隻能有一項可以設置爲“true”)、Text(下拉列表的文字)、Value(下拉列表的值)。四個成員的屬性設置如下表所:示
ID屬性 成員 |
Enabled |
Selected |
Text |
Value |
0 |
True |
True |
不保存 |
no |
1 |
True |
False |
一天 |
oneday |
2 |
True |
False |
一週 |
oneweek |
3 |
True |
False |
一個月 |
onemonth |
各組件擺放位置如圖10.40所示:
圖10.40
頁面文件編輯完畢,下面我們該考慮如何編寫邏輯文件,思路如下:
每當頁面被加載時,邏輯文件首先判定本頁是被POST方法請求而訪問的,還是被直接訪問的。如果是前者,則要接收POST方法傳過來的用戶名和密碼值,並與正確值對比;一旦用戶名和密碼值錯誤,則清空所有Cookie,返回本頁;如果用戶名密碼正確,則賦予瀏覽者相應的Cookie及有效期。按下“退出系統”按鈕,後臺邏輯腳本負責清空上一Cookie。在“解決方案資源管理器”中雙擊邏輯文件Cookie.cs,如圖10.41:
圖10.41
10.3.3 Cookie.aspx的邏輯代碼
在Cookie.cs中輸入以下代碼:
/*--------------------------------------------------------------------------------------------------------------------------------
以下諸句爲Visual Studio 2005 創建每個邏輯文件而自動生成的代碼,即引用了可能在編程中使用的一些類,這和Flash類文件中的“import ……”很相似:引用類的實例之前必須要事先引用類。
---------------------------------------------------------------------------------------------------------------------------------*/
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
/*--------------------------------------------------------------------------------------------------------------------------------
下句也是軟件自動生成的代碼,默認情況下,你的.aspx的前綴叫什麼名,就引用邏輯文件的什麼類,本例Cookie.aspx即引用Cookie類,冒號代表左邊是右邊的子類。本例中Cookie類屬於System.Web.UI.Page的子類。
---------------------------------------------------------------------------------------------------------------------------------*/
public partial class Cookie : System.Web.UI.Page
{
/*--------------------------------------------------------------------------------------------------------------------------------
因爲我們要接收用戶名、密碼、Cookie生存期的值,所以必須事先聲明變量。我們分別聲明瞭兩個“string”字符串類型變量:uid和pwd和int整形變量exp_time。爲了防止瀏覽器讀取可惡的緩存,我們還要聲明一個隨機數作爲URL地址後面的隨機參數。
---------------------------------------------------------------------------------------------------------------------------------*/
private string uid;
private string pwd;
public int exp_time;
Random r = new Random();
/*-----------------------------------------------------------------------------------------------------------------
下句爲Visual Studio 2005 軟件自動生成的代碼,前邊我們提到過Page_Load是一個觸發事件,即“當頁面被加載”。它在當頁面文件第一句AutoEventWireup爲true時可以被邏輯文件使用。一旦我們需要有在頁面加載時初始化的設置時統統可以寫在這個代碼塊內。
------------------------------------------------------------------------------------------------------------------*/
protected void Page_Load(object sender, EventArgs e)
{
/*-----------------------------------------------------------------------------------------------------------------
以下前兩句分別聲明瞭兩個HttpCookie類的實例:myCookie(用於存儲Cookie)和Cookie(用於讀取Cookie),someCookie是本例Cookie的名稱。由於默認情況下瀏覽者是未登錄的,所以根本談不上退出系統,myLB組件的Visible(可見性)屬性當然也要設置爲false,以上是初始化代碼。
------------------------------------------------------------------------------------------------------------------*/
HttpCookie myCookie = new HttpCookie("someCookie");
HttpCookie Cookie = Request.Cookies["someCookie"];
myLB.Visible = false;
if (!IsPostBack)
/*-----------------------------------------------------------------------------------------------------------------
注意:上面的代碼比較常用,意爲 “如果(不是 被POST方式提交的)”,它被用於判斷本頁面是否爲被“POST”方法。如果本句返回“true”,則不是被“POST”請求方式提交的。
------------------------------------------------------------------------------------------------------------------*/
{
//如果本頁Cookie對象不爲空,則向下進行
if (Cookie != null)
//如果本頁Cookie對象名爲auth的值爲admin
{
if (Cookie.Values["auth"] == "admin")
//返回登錄信息,羣組面板不可見,LinkButton組件可見
{
Response.Write("你已登錄系統");
myPanel.Visible = false;
myLB.Visible = true;
}
}
else
{
//如果沒有登錄成功,則羣組面板可見
myPanel.Visible = true;
}
}
else
//如果!IsPostBack的結果爲false,即本頁是POST請求過來的
{
//uid變量的值爲myUID輸入框的值
uid = Request.Form["myUID"];
//pwd變量的值爲myPWD輸入框的值
pwd = Request.Form["myPWD"];
/*---------------------------------------------------------------------------------------------------------------------------------
如果uid和pwd的值分別滿足我們設定的值,則執行以下代碼。注意:爲了讓新手理解思想,我在這裏沒有連接數據庫取出用戶“lau”的密碼,而是直接賦值。
-------------------------------------------------------------------------------------------------------------------------------*/
if (uid == "lau" && pwd == "abcdefg")
{
//聲明一個字符串變量exp,它被用做接收myDDL組件選擇的生存期
string exp = myDDL.SelectedItem.Value;
//利用switch函數選擇exp變量的值
switch (exp)
{
//如果用戶選擇的是第一項不保存,則exp_time的值爲0
case "no": exp_time = 0; break;
//如果用戶選擇的是第一項“一天”,則exp_time的值爲1
case "oneday": exp_time = 1; break;
//如果用戶選擇的是第一項“一週”,則exp_time的值爲7
case "oneweek": exp_time = 7; break;
//如果用戶選擇的是第一項“一個月”,則exp_time的值爲30
case "onemonth": exp_time = 30; break;
//默認情況,如果都沒有選,則exp_time的值爲0
default: exp_time = 0; break;
}
//myCookie這個集合填加一個名爲“auth”,值爲“admin”的 Cookie
myCookie.Values.Add("auth", "admin");
/*---------------------------------------------------------------------------------------------------------------------
如果“exp_time”的值“不爲零”,則myCookie的生存期爲從現在到增加的天數。注意:DataTime.Now方法可以返回當前時間,AddDays方法可以增加相應天數實際應用中你還可以使用其他方法使Cookie生存期精確到分和秒
--------------------------------------------------------------------------------------------------------------------*/
if(exp_time!=0){
myCookie.Expires = DateTime.Now.AddDays(exp_time);
}
/*--------------------------------------------------------------------------------------------------------------------
Response類的Cookies對象集合增加一個新的成員myCookie,注意:只有有這句代碼,以上的Cookie設定纔有效。
--------------------------------------------------------------------------------------------------------------------*/
Response.Cookies.Add(myCookie);
/*-------------------------------------------------------------------------------------------------------------------
設定Cookie之後,我們將刷新頁面,爲了使頁面不讀緩存,可以在本頁URL
後面加一個GET參數,它是0-9999中任意一個整數
--------------------------------------------------------------------------------------------------------------------*/
Response.Redirect("Cookie.aspx?rand=" + r.Next(10000));
}
}
}
/*------------------------------------------------------------------------------------------------------------------
這個代碼塊是爲“退出登錄”這個文本按鈕增加動作。注意:這個代碼塊是一個事件觸發事件,你必須在.aspx頁面的相應位置定義它。例如,返回到Cookie.aspx,把myLB組件的標籤修改爲:
<asp:LinkButton ID="myLB" runat="server" OnClick="myLB_Click">退出系統</asp:LinkButton>;還有一種更簡單的“自動生成”辦法:只要你回到Cookie.aspx的“設計”狀態,雙擊myLB組件就可以看自動添加並轉到本代碼塊,你只需要在代碼塊中填加以下代碼:
--------------------------------------------------------------------------------------------------------------------*/
protected void myLB_Click(object sender, EventArgs e)
{
/*--------------------------------------------------------------------------------------------------------------
聲明myCookie爲名爲auth的Cookie,且此Cookie的生存期爲現在(立刻過期),清除Cookie之後,頁面被重定向至本頁,URL帶有一個在0-9999的隨機數
---------------------------------------------------------------------------------------------------------------*/
HttpCookie myCookie = new HttpCookie("someCookie");
myCookie.Expires = DateTime.Now;
Response.Cookies.Add(myCookie);
Response.Redirect("Cookie.aspx?del=true&rand=" + r.Next(10000));
}
}
10.3.4 編寫Cookie.aspx頁面文件
在“解決方案資源管理器”中雙擊Cookie.aspx,寫入代碼如下:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile=
"Cookie.aspx.cs" Inherits="Cookie" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Cookie測試</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Panel ID="myPanel" runat="server" Height="89px"
Width="260px">
用戶名:<asp:TextBox ID="myUID" runat="server">
</asp:TextBox> <br />
密 碼:<asp:TextBox ID="myPWD" runat="server" TextMode=
"Password"></asp:TextBox> <br/>
<asp:DropDownList ID="myDDL" runat="server">
<asp:ListItem Selected="True" Value="no">不保存</asp:ListItem>
<asp:ListItem Value="oneday">一天</asp:ListItem>
<asp:ListItem Value="oneweek">一週</asp:ListItem>
<asp:ListItem Value="onemonth">一個月</asp:ListItem>
</asp:DropDownList><br/>
<asp:Button ID="myBTN" runat="server" Text="submit" />
</asp:Panel>
<asp:LinkButton ID="myLB" runat="server" OnClick=
"myLB_Click">退出系統</asp:LinkButton></div>
</form>
</body>
</html>
執行效果如圖10.42所示:
圖10.42
當輸入正確的用戶名和密碼之後轉向的隨機頁面如圖10.43所示:
圖10.43
* 注:這個示例的源文件在附帶光盤下 第十章\3\cookie.aspx和cookie.aspx.cs
注意:只要你沒有清空Cookies,此Cookie在其整個生存期都有效,你不妨重新打開瀏覽器試試效果。Cookie給我們帶來很大方便,例如:在製作Flash留言本時,如果某些留言是隻有高級會員才能觀看的,我們就可以用ASP.NET檢測客戶端Cookie,如果存在並且滿足觀看權限,則生成其完整信息的XML信息,反之則生成受限制的XML信息。
10.3.5 ASP.NET中的Session
說完了Cookie,我們再來說說Session。它和Cookie類似,都可以用變量值表示瀏覽者的身份,不同的是:Cookie存於客戶端,而Session變量存於服務器。未經授權,你可以修改甚至僞造一個Cookie,但你不能修改Session,在安全性方面,Session明顯更勝一籌,但如果瀏覽者較多,Session保存時間較長,勢必會給服務器造成較大的負擔。所以,現在流行的辦法是涉及到“管理”時採用“Cookie+Session雙驗證”,而普通會員只採取“Cookie單驗證”,這樣會使安全性和服務器負載達到較好的平衡。
在使用Session對象之前,我們有必要對ASP.NET中的Session有一個概念性的瞭解:
由於Session被保存在服務器上,不需要對客戶端執行什麼操作。所以Session的使用方法較Cookie要容易的多,常用的Session操作如下表所示:
對象名: |
Session |
賦予Session: |
Session["鍵名"]=鍵值; |
取得Session: |
Session["鍵名"] |
銷燬Session: |
Session.Abandon(); |
10.3.6 在ASP.NET中練習使用Session
我們還是在示例中學習ASP.NET中Session的用法。在Visual Studio 2005“解決方案資源管理器”下的地球圖標上點右鍵→“添加一個新項目”,命名爲Session.aspx,稍等片刻即可在“解決方案資源管理器”看到頁面文件和邏輯文件。
在Session.aspx的設計界面,從工具箱裏拖入工作區一個Panel組件、兩個TextBox組件、一個Button組件和一個LinkButton組件。命名方式和上一例子相同:分別爲myPanel、myUID、myPWD、myBTN和myLB。由於Session默認生存期爲20分鐘,所以我們並不需要上例的DropDownList下拉菜單。擺放順序與上例類似,如圖10.44所示:
圖10.44
雙擊myLB文本按鈕,Visual Studio 2005軟件將自動轉到其邏輯文件中,並且爲此按鈕增加了一個邏輯代碼塊。代碼如圖10.45所示:
圖10.45
雙擊時,頁面代碼Session.aspx關於myLB標籤也自動增加了一個觸發代碼:
<asp:LinkButton ID="myLB" runat="server" OnClick="myLB_Click">退出管理</asp:LinkButton>
10.3.7 邏輯代碼的編寫
在“解決方案資源管理器”中點選Session.aspx下面處於摺疊狀態的Session.aspx.cs,在其中輸入如下代碼:
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class _Session : System.Web.UI.Page
{
//下面代碼聲明瞭用於接收用戶名,密碼,隨機數的變量
private string uid;
private string pwd;
Random r = new Random();
protected void Page_Load(object sender, EventArgs e)
{
//頁面初始化時,“退出登錄”這個連接是不可見的
myLB.Visible=false;
//如果本頁不是被POST提交而訪問的
if(!IsPostBack){
//如果Sesson對象集中auth子集的值爲admin
if(Session["auth"]=="admin"){
//返回登錄信息
Response.Write("你已登錄管理狀態");
//登陸羣組不可見
myPanel.Visible=false;
//一旦登錄,“退出登錄”這個按鈕就可見
myLB.Visible=true;
//如果密碼錯誤,則重新進行登錄循環
}else{
myPanel.Visible=true;
}
}else{
//用uid和pwd這兩個變量接收文本輸入框的值
uid = Request.Form["myUID"];
pwd = Request.Form["myPWD"];
//如果滿足用戶名和密碼值
if (uid == "lau" && pwd == "abcdefg")
{
//賦予Session
Session["auth"] = "admin";
//返回隨機頁面
Response.Redirect("Session.aspx?rand=" + r.Next(10000));
}
}
}
//這是剛纔雙擊myLB組件生成的代碼塊
protected void myLB_Click(object sender, EventArgs e)
{
//銷燬Session
Session["auth"] = null;
Session.Abandon();
//跳轉到隨機頁面
Response.Redirect("Session.aspx?rand="+r.Next(100));
}
}
10.3.8 編寫Session頁面文件
邏輯代碼文件編寫完成之後,我們來編寫頁面文件Session.aspx,在“解決方案資源管理器”中雙擊Session.aspx,在其中輸入代碼如下:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Session.aspx.cs" Inherits="_Session" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Session測試</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Panel ID="myPanel" runat="server" Height="89px"
Width="260px">
用戶名:<asp:TextBox ID="myUID" runat="server">
</asp:TextBox> <br />
密 碼:<asp:TextBox ID="myPWD" runat="server"
TextMode="Password"></asp:TextBox> <br />
<br/>
<asp:Button ID="myBTN" runat="server" Text="submit"/>
</asp:Panel>
<asp:LinkButton ID="myLB" runat="server" OnClick="myLB_Click">退出管理</asp:LinkButton></div>
</form>
</body>
</html>
調試效果如圖10.46所示:
圖10.46
輸入正確的密碼之後,效果如圖10.47所示:
圖10.47
* 注:這個示例的源文件在附帶光盤 第十章\4\session.aspx和session.aspx.cs
關閉瀏覽器或20分鐘後不執行操作,Session將過期。
通過本節學習,我們對ASP.NET中的Cookie和Session使用有了一個概括性瞭解。建議讀者自己多多嘗試。