Form验证
代碼寫(xiě) N 久了,總想寫(xiě)得別的。這不,上頭說(shuō)在整合兩個(gè)項(xiàng)目,做成單一登錄(Single Sign On),也有人稱(chēng)之為“單點(diǎn)登錄”。查閱相關(guān)文檔后,終于實(shí)現(xiàn)了,現(xiàn)在把它拿出來(lái)與大家一起分享。或許大家會(huì)問(wèn):“這與標(biāo)題不符呀?”別急,在下筆之前,我腦子里想到了我剛使用 Form 認(rèn)證時(shí)遇到的一些問(wèn)題,以及使用過(guò)程用到的一些技巧(實(shí)乃投機(jī)取巧是也 ^_^ )。偶打初中那時(shí),語(yǔ)文水平就不怎么滴,考試常常作文寫(xiě)不出來(lái),所以寫(xiě)作水平有限,還請(qǐng)大家海量。對(duì)了,本人不僅寫(xiě)作水平有限,編程能力也不是很好,此文供大家學(xué)習(xí)交流之用,歡迎廣大勞苦群眾拎著雞蛋、捧著鮮花前來(lái)評(píng)論。轉(zhuǎn)載請(qǐng)注明原創(chuàng)作者乃寒羽楓是也,不甚感激!
廢話也說(shuō)的差不多了,言歸正傳, ASP.NET 的安全認(rèn)證,共有“Windows”“Form”“Passport”“None”四種驗(yàn)證模式。“Windows”與“None”沒(méi)有起到保護(hù)的作用,不推薦使用;“Passport”我又沒(méi)用過(guò),唉……所以我只好講講“Form”認(rèn)證了。我打算分三部分:
第一部分——怎樣實(shí)現(xiàn)From 認(rèn)證;
第二部分—— Form 認(rèn)證的實(shí)戰(zhàn)運(yùn)用;
第三部分——實(shí)現(xiàn)單點(diǎn)登錄(Single Sign On)
第一部分如何運(yùn)用 Form 表單認(rèn)證
一、新建一個(gè)測(cè)試項(xiàng)目
為了更好說(shuō)明,有必要新建一個(gè)測(cè)試項(xiàng)目(暫且為“FormTest”吧),包含三張頁(yè)面足矣(Default.aspx、Login.aspx、UserInfo.aspx)。啥?有人不會(huì)新建項(xiàng)目,不會(huì)新增頁(yè)面?你問(wèn)我咋辦?我看這么辦好了:拖出去,打回原藉,從幼兒園學(xué)起……
二、修改 Web.config
1、 雙擊項(xiàng)目中的Web.config(不會(huì)的、找不到的打 PP)
2、 找到下列文字<authenticationmode="Windows"/> 把它改成:
<authenticationmode="Forms">
<formslogi nUrl="Login.aspx"name=".ASPXAUTH"></forms>
</authentication>
3、 找到<authorization><allowusers="*"/></authorization>換成
<authorization><denyusers="?"></deny></authorization>
這里沒(méi)什么好說(shuō)的,只要拷貝過(guò)去就行。雖說(shuō)如此,但還是有人會(huì)弄錯(cuò),如下:
<authenticationmode="Forms">
<formslogin Url="Login.aspx"name=".APSX"></forms>
<denyusers="?"></deny>
</authentication>
若要問(wèn)是誰(shuí)把<denyusers="?"></deny>放入<authentication>中的,我會(huì)很榮幸地告訴你,那是 N 年前的我:<authentication>與<authorization>都是以auth字母開(kāi)頭又都是以ation結(jié)尾,何其相似;英文單詞背不下來(lái)的我以為他們是一伙的……
三、編寫(xiě) .cs 代碼——登錄與退出
1、 登錄代碼:
a、 書(shū)本上介紹的
private void Btn_Login_Click(object sender, System.EventArgs e)
???????? {
if(this.Txt_UserName.Text=="Admin" && this.Txt_Password.Text=="123456")
????????????? {
System.Web.Security.FormsAuthentication.RedirectFromLoginPage(this.Txt_UserName.Text,false);
????? }
}
b、 偶找了 N 久才找到的
private void Btn_Login_Click(object sender, System.EventArgs e)
???????? {
if(this.Txt_UserName.Text=="Admin" && this.Txt_Password.Text=="123456")
????????????? {
System.Web.Security.FormsAuthentication.SetAuthCookie(this.Txt_UserName.Text,false);
???? Response.Redirect("Default.aspx");
???? }
}
以上兩種都可發(fā)放驗(yàn)證后的Cookie,即通過(guò)驗(yàn)證,區(qū)別:
方法 a) 指驗(yàn)證后返回請(qǐng)求頁(yè)面,俗稱(chēng)“從哪來(lái)就打哪去”。比如:用戶沒(méi)登錄前直接在 IE 地址欄輸入http://localhost/FormTest/UserInfo.aspx,那么該用戶將看到的是Login.aspx?ReturnUrl=UserInfo.aspx,輸入用戶名與密碼登錄成功后,系統(tǒng)將根據(jù)“ReturnUrl”的值,返回相應(yīng)的頁(yè)面
方法 b) 則是分兩步走:通過(guò)驗(yàn)證后就直接發(fā)放Cookie,跳轉(zhuǎn)頁(yè)面將由程序員自行指定,此方法多用于Default.aspx 使用框架結(jié)構(gòu)的系統(tǒng)。
2、 退出代碼:
private void Btn_LogOut_Click(object sender, System.EventArgs e)
???? {
System.Web.Security.FormsAuthentication.SignOut();
}
四、如何判斷驗(yàn)證與否及獲取驗(yàn)證后的用戶信息
有的時(shí)候,在同一張頁(yè)面需要判斷用戶是否已經(jīng)登錄,然后再呈現(xiàn)不同的布局。有人喜歡用Session來(lái)判斷,我不反對(duì)此類(lèi)做法,在此我只是想告訴大家還有一種方法,且看下面代碼:
if(User.Identity.IsAuthenticated)
???????? {
//你已通過(guò)驗(yàn)證,知道該怎么做了吧?
}
User.Identity還有兩個(gè)屬性AuthenticationType(驗(yàn)證類(lèi)型)與Name(用戶名稱(chēng)),大家要注意的是Name屬性,此處的User.Identity.Name將得到,驗(yàn)證通過(guò)(RedirectFromLoginPage或SetAuthCookie)時(shí),我們帶入的第一個(gè)參數(shù)this.Txt_UserName.Text 。這個(gè)參數(shù)很重要,關(guān)系到種種……種種的情況,何出此言,且聽(tīng)下回分解……
第二部分 Form 認(rèn)證的實(shí)戰(zhàn)運(yùn)用
話說(shuō)上回,簡(jiǎn)單地說(shuō)了一下 Form 表單認(rèn)證的用法。或許大家覺(jué)得太簡(jiǎn)單,對(duì)那些大內(nèi)高手來(lái)說(shuō)應(yīng)該是“灑灑水啦”“小 Kiss 啦(小意思)”。今天咱們來(lái)點(diǎn)的花樣吧:古有六扇門(mén),拒收葉孤城;東門(mén)不刮風(fēng),吹雪姓西門(mén);緞帶作憑證,決戰(zhàn)紫禁城。
五、Web.config 的作用范圍
新建項(xiàng)目時(shí), VS.Net 會(huì)在項(xiàng)目根目錄建立一個(gè)內(nèi)容固定的 Web.config。除了在項(xiàng)目根目錄,你還可以在任一目錄下建立 Web.config ,條件就是應(yīng)用程序級(jí)別的節(jié)點(diǎn)只能在根目錄的 Web.config 中出現(xiàn)。至于哪些是應(yīng)用程序級(jí)別節(jié)點(diǎn)呢,這個(gè)問(wèn)題嘛,其實(shí)我也不太清楚,呵呵。電腦不是我發(fā)明的,微軟不是我創(chuàng)建的,C# 更不是我說(shuō)了算的,神仙也有不知道的,所以我不曉得是正常的。話雖如此,只要它不報(bào)錯(cuò),那就是對(duì)的。
關(guān)于 Web.config 設(shè)置的作用范圍,記住以下兩點(diǎn):
1、? Web.config 的設(shè)置將作用于所在目錄的所有文件及其子目錄下的所有東東(繼承:子隨父姓)
2、 子目錄下的 Web.config 設(shè)置將覆蓋由父目錄繼承下來(lái)的設(shè)置(覆蓋:縣官不如現(xiàn)管)
給大家提個(gè)問(wèn)題:有沒(méi)有比根目錄Web.config 的作用范圍還大的配置文件呢?看完第三部分便知分曉。
六、學(xué)會(huì)拒絕與巧用允許
回到我們?cè)诘谝换睾闲陆ǖ臏y(cè)試項(xiàng)目“FormTest”, 既然要進(jìn)行驗(yàn)證,按國(guó)際慣例,就得有用戶名與密碼。那,這些用戶是管理員自己在數(shù)據(jù)庫(kù)建好呢,還是用戶注冊(cè)、管理員審核好呢。只要不是一般的笨蛋,都知道選擇后者。你們還別說(shuō),我公司還真有個(gè)別項(xiàng)目是管理員連到數(shù)據(jù)庫(kù)去建帳號(hào)的,屬于比較特殊的笨蛋,咱們不學(xué)他也罷,還是老老實(shí)實(shí)添加兩個(gè)頁(yè)面吧——注冊(cè)頁(yè)面(Register.aspx)與審核頁(yè)面(Auditing.aspx)。
問(wèn)題終于就要浮出水面啦,當(dāng)你做好Register.aspx時(shí),想訪問(wèn)它的時(shí)候突然覺(jué)得不對(duì)勁,怎么又回到了登錄頁(yè)面?你仔細(xì)瞧瞧網(wǎng)址,是不是成了:Login.aspx?ReturnUrl=Register.aspx。怎么辦,用戶就是因?yàn)闆](méi)有帳號(hào)才去訪問(wèn)注冊(cè)頁(yè)面的呀?(這句純屬?gòu)U話,有帳號(hào)誰(shuí)還跑去注冊(cè)。)我時(shí)常對(duì)我的同事說(shuō):“辦法是人想出來(lái)滴!!”
1、新建一個(gè)目錄Public,用于存放一些公用的文件,如萬(wàn)年歷、腳本呀……
2、在“解決方案資源管理器”中右擊點(diǎn)擊目錄Public,新增一個(gè)Web.config
3、把上述Web.config的內(nèi)容統(tǒng)統(tǒng)刪除,僅留以下即可:
<?xmlversion="1.0"encoding="utf-8"?>
<configuration>
<system.web>
<authorization><allow users="*"/></authorization>
</system.web>
</configuration>
終于切入正題了,不容易呀。根據(jù)“覆蓋”原則,我們知道上述Web.config將替代根目錄Web.config中的<authorization>節(jié)點(diǎn)設(shè)置,即:
<allowusers="*"/>替換<denyusers="?"></deny>
注解:“allow”允許的意思;“*”表示所有用戶;
“deny”拒絕的意思;“?”表示匿名用戶;
因此,處于Public目錄下的文件,允許所有人瀏覽,包括未驗(yàn)證的用戶。把Register.aspx拖進(jìn)來(lái)吧,再也不會(huì)有人阻止你瀏覽啦。
除了注冊(cè)頁(yè)面,我們還提到一個(gè)審核頁(yè)面(Auditing.aspx),審核權(quán)限一般都在管理員或主管手里,并不想讓其他人瀏覽此頁(yè)面(真理往往掌握在少數(shù)人的手里,這也是沒(méi)法子的事),怎么辦?“辦法是人想出來(lái)滴”呵呵……新建一個(gè)管理員的目錄ManageSys,在此目錄下再新增一個(gè)Web.config。內(nèi)容如下:
<?xmlversion="1.0"encoding="utf-8"?>
<configuration>
<system.web>
<authorization>
<allow users="Admin"/>
<deny users="*"/>
</authorization>
</system.web>
</configuration>
現(xiàn)在的問(wèn)題就是怎么才能知道誰(shuí)是“Admin”呢,這個(gè)問(wèn)題就有點(diǎn)象“我的鞋底有個(gè)洞”——天不知地知,你不知我知。閑話少說(shuō)(要是有稿費(fèi)多好,我就有多寫(xiě)幾個(gè)字的動(dòng)力,唉……),大家還記得我在第一部分的結(jié)尾嗎?什么,忘啦!罰你回去看一百遍,記住了再回來(lái)。站住,回來(lái)!一想到你的記性,我就不放心,第一部分的瀏覽網(wǎng)址是http://blog.csdn.net/cityhunter172/archive/2005/11/06/524043.aspx,回到此處的網(wǎng)址是http://blog.csdn.net/cityhunter172/archive/2005/11/13/528463.aspx
好了,不管那些記不好的家伙了,大伙繼續(xù)往下看。
System.Web.Security.FormsAuthentication.SetAuthCookie(this.Txt_UserName.Text,false);//通過(guò)驗(yàn)證,發(fā)放Cookie
之前我曾強(qiáng)調(diào),要注意,第一個(gè)參數(shù)很重要,重要到什么程度?說(shuō)到這,恐怕地球人都知道了——它就是allow與deny的依據(jù)。假如此處用戶填寫(xiě)的是“Admin”即this.Txt_UserName.Text="Admin";那么進(jìn)入系統(tǒng)后,他就能訪問(wèn)ManageSys目錄下的網(wǎng)頁(yè)了,其它閑雜人等一律拒之門(mén)外。
為鞏固上述內(nèi)容,給大伙留個(gè)課外作業(yè):此項(xiàng)目有兩部門(mén)使用,其中每個(gè)部門(mén)分別都有些特定的頁(yè)面僅供本部門(mén)用戶瀏覽使用,請(qǐng)問(wèn)該如何使用Web.config達(dá)到效果?同樣,答案在第三部分揭曉
七、分散與集中
乍看之下,就象是馬克思列寧主義、***思想、***理論中的辯證關(guān)系,大伙放心,偶是學(xué)理科的,只明白“高舉程序員的偉大旗幟,以編寫(xiě)代碼為中心”。停……
到目前為此,我們的測(cè)試項(xiàng)目“FormTest”已經(jīng)擁有兩個(gè)目錄三個(gè)Web.config,伴隨用戶需求的多樣化,Web.config也會(huì)越來(lái)越多,比如常用的文件上傳功能等等。眾多的Web.config分布在不同的目錄里面,維護(hù)起來(lái)肯定比較煩人。能不能集中起來(lái)管理呢,應(yīng)該咋辦哩?“辦法是……”喲,有人先說(shuō)出來(lái)啦。不錯(cuò),“辦法的確是人想出來(lái)滴”,我不說(shuō),你是不是只有在一邊涼伴?開(kāi)玩笑的,為了讓更多的人記住這句話,我打算告訴你集中管理的辦法。
要想集中管理,不得不用到<location>節(jié)點(diǎn)與path屬性。在本項(xiàng)目中,我們將目錄Public與ManageSys下的設(shè)置放在根目錄下的Web.config里面,如下:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<location path="Public">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
<location path="ManageSys">
<system.web>
<authorization>
<allow users="Admin"/>
<deny users="*"/>
</authorization>
</system.web>
</location>
<system.web>
<!--這里放置原來(lái)根目錄Web.config的內(nèi)容,就不列出來(lái)了-->
</system.web>
</configuration>
需要提醒的是
1、<location>節(jié)點(diǎn)的位置是在<configuration>的一個(gè)子節(jié)點(diǎn),它與原有的<system.web>屬于并列關(guān)系
2、<location>節(jié)點(diǎn)只需要放入對(duì)應(yīng)子目錄Web.config中的<system.web>的節(jié)點(diǎn)內(nèi)容
八、額外的保護(hù)
第二部分就要結(jié)束了,現(xiàn)在時(shí)間已是凌晨4點(diǎn)50分,我容易嘛我。認(rèn)證的目的就是為了防止他人非法瀏覽頁(yè)面,或未經(jīng)許可使用某些功能。當(dāng)然,世上沒(méi)有絕對(duì)的安全,如今MD5加密都被我們國(guó)人給破解了,就是最好的例證。
細(xì)心的人可能早就發(fā)現(xiàn)ASP.NET的安全認(rèn)證只針對(duì).aspx、.ascx……等ASP.NET文件起作用,而對(duì)普通頁(yè)面與文件卻“視而不見(jiàn)”,如.htm、.js、.jpg等。通過(guò)以下步驟你就可以保護(hù)你想保護(hù)的文件類(lèi)型。
1、打開(kāi)Internet信息服務(wù)(IIS)管理器→右擊本項(xiàng)目虛擬→屬性,如下圖
????????? (http://blog.csdn.net/images/blog_csdn_net/cityhunter172/85935/r_aspxForm01.JPG)
2、點(diǎn)擊按鈕“配置”,出現(xiàn)如下對(duì)話框:
(http://blog.csdn.net/images/blog_csdn_net/cityhunter172/85935/r_aspxForm02.JPG)
3、雙擊.aspx的應(yīng)用程序擴(kuò)展→查看對(duì)話框內(nèi)容,如下圖:
(http://blog.csdn.net/images/blog_csdn_net/cityhunter172/85935/r_aspxForm03.JPG)
4、復(fù)制“可執(zhí)行文件”的全路徑名稱(chēng)后→點(diǎn)擊“取消”返回上一層對(duì)話框→點(diǎn)擊按鈕“添加”
5、粘貼剛才復(fù)制的內(nèi)容(我的系統(tǒng)裝在D盤(pán),所以內(nèi)容為D:"WINDOWS"Microsoft.NET"Framework"v1.1.4322"aspnet_isapi.dll)→填寫(xiě)后綴名為.htm→填寫(xiě)動(dòng)作限制為“GET,HEAD,POST,DEBUG”(為方便省事你可選全部)
6、最后點(diǎn)擊“確定”→往項(xiàng)目中添加HtmlPage1.htm→在IE瀏覽器的地址欄直接輸入http://localhost/FormTest/HtmlPage1.htm→觀看測(cè)試效果
最后送大家一段Web.config設(shè)置,發(fā)完睡覺(jué),實(shí)在是困的不行了。
<location path="決戰(zhàn)紫禁城">
<system.web>
<authorization>
<allow users="葉孤城"/>
<allow users="西門(mén)吹雪"/>
<deny users="*"/>
</authorization>
</system.web>
</location>
<location path="金鑾殿屋脊">
<system.web>
<authorization>
<allow users="腰系緞帶之人"/>
<deny users="*"/>
</authorization>
</system.web>
</location>
第三部分實(shí)現(xiàn)單點(diǎn)登錄(SingleSignOn)
“等了好久終于等到今天,寫(xiě)了好久終于就快完結(jié),但是網(wǎng)友的反應(yīng)卻讓我有一些的傷心。盼了好久終于盼到今天,忍了好久終于把此文撰寫(xiě),那些受冷落的無(wú)奈早就無(wú)所謂,累也不說(shuō)累”(歌詞《今天》新演繹)。看著人家的Blog文章的評(píng)論是一條接一條,再瞧瞧自己:“無(wú)人問(wèn)津吶,真…無(wú)…奈……唉,沒(méi)人理我,還是回家吧。”“哎,還沒(méi)開(kāi)始寫(xiě),怎么就走了?回去干什么呢?”回去寫(xiě)作業(yè)去啊,上回交待的課外作業(yè)你做了沒(méi)?(注:http://blog.csdn.net/cityhunter172/archive/2005/11/13/528463.aspx在第二部分第六節(jié)布置的課外作業(yè):此項(xiàng)目有兩部門(mén)使用,其中每個(gè)部門(mén)分別都有些特定的頁(yè)面僅供本部門(mén)用戶瀏覽使用,請(qǐng)問(wèn)該如何使用Web.config達(dá)到效果?)
不知有多少人做了作業(yè),其實(shí)答案并不難。只需要在驗(yàn)證用戶名與密碼后,取得該用戶的部門(mén)名稱(chēng)或部門(mén)代碼,把它作為判斷的依據(jù)就行了。最好不要用部門(mén)的數(shù)字ID,那樣不利于以后的維護(hù)。
有一個(gè)秘密,一般人我不告訴他。Web.config中的<location>節(jié)點(diǎn)的path屬性可以是一張具體頁(yè)面的相對(duì)URL路徑,如下:<location path="ManageSys/Auditing.aspx">
好了,接下來(lái)就要揭開(kāi)“比根目錄Web.config的作用范圍還大的配置文件”之謎啦,它就是藏匿在Windows系統(tǒng)目錄下,支配整個(gè).NetFramework配置的傳說(shuō)中的Machine.config!!下面請(qǐng)大家以熱烈的掌聲,歡迎我們這位神秘俠客的閃亮登場(chǎng)……
九、Machine.config
Machine.config,性別不詳,年齡未知,家庭出身:XML。深藏于“云深不知處”的操作系統(tǒng)目錄下的某某地方(注:C:"WINDOWS【或WINNT】"Microsoft.NET"Framework"v1.1.4322【或v1.0.3705】"CONFIG),控制著“更上一層樓”的.NETFramework的本機(jī)配置。接下來(lái)簡(jiǎn)要的講解一下它的內(nèi)容,以及它與Web.config的關(guān)系。
經(jīng)過(guò)“松下問(wèn)童子”,我們好不容易找到這位隱者,打開(kāi)一看,乖乖,足有3700多行!!“叫我怎么能不難過(guò),偶只想看看是啥結(jié)構(gòu),可內(nèi)容實(shí)在是太多太繁瑣……”還記得偶經(jīng)常對(duì)同事說(shuō)的一句話么:“辦法是人想出來(lái)的!”它不是有三千七百多行嗎,那我們就不管三七能否得出二十一啦,把它拷出來(lái)先。它不是XML出身嗎,那咱們就還其正身,重新命名為“machine.xml”。接著用IE瀏覽器將這位改頭換面的隱者打開(kāi),把節(jié)點(diǎn)與注釋一一合攏。這回你看到了吧,是不是很有成就感?你要是想謝謝我,就讓我看到你在此文下面的評(píng)論吧。多多益善,呵呵。
Machine.config與Web.config是啥關(guān)系?四個(gè)字——父子關(guān)系。記得我在第二部分第五節(jié)講解Web.config作用范圍的時(shí)提到兩點(diǎn)——繼承與覆蓋(詳見(jiàn)http://blog.csdn.net/cityhunter172/archive/2005/11/13/528463.aspx),在此也同樣適用。
1、Machine.config中的設(shè)置將作用于運(yùn)行在本機(jī)的所有站點(diǎn)及其虛擬目錄,遇到子目錄將一直繼承下去。
2、Web.config中的設(shè)置將覆蓋由Machine.config中繼承下來(lái)的對(duì)應(yīng)的節(jié)點(diǎn)設(shè)置
說(shuō)到這,再告訴大家一個(gè)秘密——“世上本無(wú)秘密,知道的人多了,便成了不是秘密的秘密!”
a、Machine.config中的<system.web>節(jié)點(diǎn)所有內(nèi)容都能出現(xiàn)在項(xiàng)目根目錄下的Web.config中,也就是說(shuō)能在Web.config中的內(nèi)容已經(jīng)在Machine.config中一一列出;
b、其中<system.web>節(jié)點(diǎn)下的<pages>還能出現(xiàn)在頁(yè)面上,如:HTML視圖下,在WebForm1.aspx的第一行加上<pages>的節(jié)點(diǎn)內(nèi)容validateRequest="false"(此句意思是不對(duì)WebForm1.aspx頁(yè)面文本框輸入的值,是否包含“<”“>”等等具有危險(xiǎn)性的代碼進(jìn)行檢查,下一節(jié)將具體運(yùn)用到)
<%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="FromTest.WebForm1" validateRequest="false"%>
十、單點(diǎn)登錄(SingleSignOn)的前提條件
之前說(shuō)了這么多關(guān)于Machine.config的事,都是為了實(shí)現(xiàn)單點(diǎn)登錄作鋪墊,那何為單點(diǎn)登錄(SingleSignOn)?從字面理解就是在一個(gè)地方登錄,通常運(yùn)用于ASP.NET分布式環(huán)境中(跨單個(gè)服務(wù)器上的多個(gè)應(yīng)用程序或在網(wǎng)絡(luò)場(chǎng)中)的Forms身份驗(yàn)證。打個(gè)比方,就好比現(xiàn)在Sohu(搜狐)與Chinren(中國(guó)校友錄)的做法,我在Sohu登錄以后就不需要在Chinaren登錄了。臺(tái)灣與香港又把SingleSignOn稱(chēng)之為“單一登入”。
要想實(shí)現(xiàn)此功能,首要條件是需要一組用于加密與驗(yàn)證加密的密鑰。它們位于Machine.config中,修改<system.web>節(jié)點(diǎn)下的<machineKey>節(jié)點(diǎn)屬性,如下:
<machineKey
firstKey="172"
copyrightKey="Cityhunter172"
validationKey="AD117F2F286CDCB15A9D1D4535E16DB0248026939**AUTHOR**CITYHUNTER172****WEBSITE**172*MEIBU*COM****MAILTO**CITYHUNTER172@126*COM*****F2F286CDCB15A9D1D4535E16DB0248026939"
secondKey="meibu"
decryptionKey="3C89AE62AD117F2F286CDCB15A9D1D4535E16DB0248026939" validation="SHA1"
thirdKey="com"
/>
1、validationKey為用于驗(yàn)證加密數(shù)據(jù)的密鑰。最小長(zhǎng)度為40個(gè)字符(20字節(jié)),最大長(zhǎng)度為128個(gè)字符(64字節(jié))。
2、decryptionKey為用于加密數(shù)據(jù)的密鑰。長(zhǎng)度只有16個(gè)字符(8字節(jié))與48個(gè)字符(24字節(jié))兩種。
3、validation為用數(shù)據(jù)驗(yàn)證使用的加密類(lèi)型。擁有“SHA1”“MD5”“3DES”三種方法
4、大伙參照上述<machineKey>試著在WebForm1.aspx運(yùn)行下列語(yǔ)句:
this.TextBox2.Text="ht"+"tp"+"://"+firstKey+"."+secondKey+"."+thirdKey
大家在修改之前請(qǐng)先備份一下Machine.config,到時(shí)要是出錯(cuò)可別怪我沒(méi)提醒你。以上密鑰并不是胡亂得來(lái)的,接下來(lái)向大家介紹生成密鑰的方法。
我們把上一節(jié)中提到的WebForm1.aspx拖入本項(xiàng)目的Public目錄下,再往頁(yè)面上拖入一個(gè)TextMode=MultiLine的TextBox3與一個(gè)Button編寫(xiě)按鈕事件與函數(shù):
privatevoidButton1_Click(objectsender,System.EventArgse)
{
stringdecStr=this.CreateKeyString(int.Parse(this.TextBox1.Text));
stringvalStr=this.CreateKeyString(int.Parse(this.TextBox2.Text));
this.TextBox3.Text=string.Format("<machineKeyvalidationKey=""{0}""decryptionKey=""{1}""validation=""SHA1""/>",valStr,decStr);
}
///<summary>
///生成加密型強(qiáng)隨機(jī)Key值
///</summary>
///<paramname="i">Key的有效長(zhǎng)度:
///decryptionKey的有效值為8或24;
///validationKay的有效值為20至64
///</param>
privatestringCreateKeyString(inti)
{
System.Security.Cryptography.RNGCryptoServiceProvider rng=newSystem.Security.Cryptography.RNGCryptoServiceProvider();//加密隨機(jī)數(shù)生成器
byte[]bt=new byte[i];
rng.GetBytes(bt);//用加密型強(qiáng)隨機(jī)值序列填充字節(jié)數(shù)組
System.Text.StringBuilder str=newSystem.Text.StringBuilder();
for(intj=0;j<i;j++)
{
str.Append(string.Format("{0:X2}",bt[j]));//轉(zhuǎn)換成大寫(xiě)的十六進(jìn)制文本
}
returnstr.ToString();
}
每次點(diǎn)擊按鈕生成密鑰都不同,大家不妨多點(diǎn)幾次。切換至HTML視圖,到WebForm1.aspx第一行把validateRequest="false"去掉,然后再多點(diǎn)幾次Button1試試,看看會(huì)有什么效果,嘿嘿………
十一、單點(diǎn)登錄(SingleSignOn)的站點(diǎn)示例
將上述TextBox3產(chǎn)生的文本,覆蓋Machine.config中的,現(xiàn)在你的機(jī)器已經(jīng)具備了單點(diǎn)登錄的條件。大伙可以再新建一個(gè)項(xiàng)目FormTest2,從FormTest2登錄后直接輸入FormTest中的Default.aspx的網(wǎng)址(http://localhost/FormTest/Default.aspx),反之亦可。
下面結(jié)合實(shí)例講解:偶在山東每步科技網(wǎng)站申請(qǐng)了一個(gè)免費(fèi)二級(jí)域名172.meibu.com,并下載了每步的4.0版的動(dòng)態(tài)域名解析客戶端。現(xiàn)在使用ADSL拔號(hào)上網(wǎng),也就是說(shuō)我的電腦已經(jīng)成了Web服務(wù)器,同時(shí)支持SQLServer、Oracle空間高達(dá)200G想怎么弄就怎么弄,夠牛吧,嘿嘿。布署上來(lái)的項(xiàng)目有環(huán)勝數(shù)碼網(wǎng)站、權(quán)限管理系統(tǒng)、IT內(nèi)部管理網(wǎng),以上三個(gè)項(xiàng)目是偶一人全權(quán)開(kāi)發(fā)的。所謂全權(quán)就是從數(shù)據(jù)庫(kù)存儲(chǔ)過(guò)程寫(xiě)到.cs代碼再到j(luò)avascript,最后到美工都是偶一手搞定的。^_^我把這三個(gè)不相干的項(xiàng)目做成了單點(diǎn)登錄的模式,加上整合站點(diǎn)的主頁(yè)面,共有四個(gè)地方可以進(jìn)行登錄。因?yàn)橛脩鬞able的結(jié)構(gòu)不同,因此只有一個(gè)入口能在進(jìn)入后,在跳轉(zhuǎn)站點(diǎn)時(shí)不會(huì)出錯(cuò),那就是在整合頁(yè)面登錄。
現(xiàn)在我想把環(huán)勝數(shù)碼這個(gè)站點(diǎn)單獨(dú)脫離出來(lái),而剩下的兩個(gè)站點(diǎn)繼續(xù)實(shí)現(xiàn)單點(diǎn)登錄,該怎么做呢?或者是我的ASP.NET的空間是租的,服務(wù)商肯定不可能讓我修改Machine.config,我又咋辦哩?“辦法是人想出來(lái)滴!!”,根據(jù)上述Machine.config與Web.config的關(guān)系,我們可以把<machineKey>節(jié)點(diǎn)放入項(xiàng)目根目錄下Web.config的<system.web>節(jié)點(diǎn)。如下:
1、權(quán)限管理系統(tǒng)項(xiàng)目的Web.config用于Form認(rèn)證的設(shè)置
<machineKeyvalidationKey="AD117F2F286CDCB15A9D1D4535E16DB0248026939**AUTHOR**CITYHUNTER172****WEBSITE**172*MEIBU*COM****MAILTO**CITYHUNTER172@126*COM*****F2F286CDCB15A9D1D4535E16DB0248026939"decryptionKey="3C89AE62AD117F2F286CDCB15A9D1D4535E16DB0248026939"validation="SHA1"/>
<authenticationmode="Forms">
<formsloginUrl="Login.aspx"name="172.MEIBU.COM_WARRANT"></forms>
</authentication>
<authorization><denyusers="?"></deny></authorization>
2、IT內(nèi)部管理網(wǎng)項(xiàng)目的Web.config用于Form認(rèn)證的設(shè)置
<machineKeyvalidationKey="AD117F2F286CDCB15A9D1D4535E16DB0248026939**AUTHOR**CITYHUNTER172****WEBSITE**172*MEIBU*COM****MAILTO**CITYHUNTER172@126*COM*****F2F286CDCB15A9D1D4535E16DB0248026939"decryptionKey="3C89AE62AD117F2F286CDCB15A9D1D4535E16DB0248026939"validation="SHA1"/>
<authenticationmode="Forms">
<formsloginUrl="Login.aspx"name="172.MEIBU.COM_IT"></forms>
</authentication>
<authorization><denyusers="?"></deny></authorization>
大家可能會(huì)迫不急待的去試一把,偶贊成這樣的做法,因?yàn)槭聦?shí)是檢驗(yàn)真理的唯一辦法。你不去試著自己動(dòng)手,光看我在這說(shuō)是很難提高的。先別急,我已經(jīng)知道你想說(shuō)什么,聽(tīng)聽(tīng)我慢慢向你解釋:
a)兩個(gè)項(xiàng)目Web.cinfig的<machineKey>節(jié)點(diǎn)確保以下幾個(gè)字段完全一樣:validationKey、decryptionKey、validation
b)兩個(gè)項(xiàng)目的Cookie名稱(chēng)必須相同,也就是<forms>中的name屬性,這里我們把它統(tǒng)一為name="172.MEIBU.COM_PROJECT"
c)注意區(qū)分大小寫(xiě)
在整合的過(guò)程中,我把遇到的問(wèn)題向大伙說(shuō)一下,以免你們走同樣的路。
1)首先應(yīng)該是用戶管理的問(wèn)題,把兩個(gè)項(xiàng)目的用戶整合在一起,可不是一件容易的事,原則是新建一個(gè)新的Table只存放帳號(hào)與密碼,用賬號(hào)做關(guān)聯(lián),編寫(xiě)觸發(fā)器,做到Table之間的同步;
2)不要指望兩個(gè)項(xiàng)目間用Session進(jìn)行傳值,兩個(gè)應(yīng)用程序的Session是無(wú)法共享的。網(wǎng)上有人曾把類(lèi)庫(kù)(編譯后的.dll文檔)放入同一個(gè)bin文件夾實(shí)現(xiàn)過(guò)Session共享,這樣的做法實(shí)際上是把兩個(gè)項(xiàng)目變相合并成一個(gè)應(yīng)用程序,不是我們所想要的,理由很簡(jiǎn)單:Sohu與Chinaren的服務(wù)器分處兩地該怎么辦?
3)項(xiàng)目間的傳值,可用Cookie實(shí)現(xiàn)。在第一部分的第三節(jié)(http://blog.csdn.net/cityhunter172/archive/2005/11/06/524043.aspx)我們介紹了只要運(yùn)行System.Web.Security.FormsAuthentication.SetAuthCookie方法即可實(shí)現(xiàn)登錄,單點(diǎn)登錄的實(shí)質(zhì)就是含有身份驗(yàn)證票的Cookie能在項(xiàng)目間共用。
接下來(lái),有必要向大家介紹一下Cookie在.Net中的用法。
十二、Cookie在ASP.NET中的用法
大家也許和我一樣,很少在ASP.NET中使用Cookie,傳參數(shù)呀,存變量呀,用的比較多的是Session或ViewState以及隱藏控件,有的干脆用“?”的請(qǐng)求方式。
1、Cookie存放的目錄
Cookie是存放在客戶端的東東,放在“TemporaryInternetFiles”目錄,所以說(shuō)存在安全性的問(wèn)題。大伙可通過(guò)以下方式找到具體位置:打開(kāi)控制面板→Internet選項(xiàng)→常規(guī)→Internet臨時(shí)文件→設(shè)置→即可看到“當(dāng)前位置”,→點(diǎn)擊“查看文件”將直接打開(kāi)該文件夾,你也可以點(diǎn)擊“移動(dòng)文件夾”變更它所在的位置。參照下圖(http://blog.csdn.net/images/blog_csdn_net/cityhunter172/85935/r_aspxForm04.jpg與http://blog.csdn.net/images/blog_csdn_net/cityhunter172/85935/r_aspxForm05.jpg)
2、Cookie的有效期
從上圖我們可以清楚的看到每個(gè)Cookie文檔的“截止期”(即為有效期)。在有效期內(nèi),當(dāng)?shù)卿浻?jì)算機(jī)的用戶Administrator再次訪問(wèn)172.meibu.com時(shí),那么IE就會(huì)在請(qǐng)求頁(yè)面的同時(shí),連同上述的名稱(chēng)為“Cookie:administrator@172.meibu.com”的Cookie文檔內(nèi)容一起發(fā)送給服務(wù)器。
若該文檔包含多個(gè)Cookie的值時(shí),截止期則以最后的失效期為準(zhǔn)。
3、Cookie的類(lèi)型
這里我們按有效期來(lái)分,分為兩種:
a)即時(shí)型
指的是關(guān)閉瀏覽器(所有瀏覽172.meibu.com的IE)后,Cookie便失效,此類(lèi)Cookie不會(huì)在“TemporaryInternetFiles”目錄出現(xiàn)。其實(shí)它也有截止期的,為“0001-01-01”
b)持久型
就是已指定具體“截止期”的,能夠在“TemporaryInternetFiles”目錄里面找到的Cookie
4、Cookie的內(nèi)容
雙擊打開(kāi)“Cookie:administrator@172.meibu.com”,我們看到以下內(nèi)容,如下圖(http://blog.csdn.net/images/blog_csdn_net/cityhunter172/85935/r_aspxForm06.jpg):
上圖中,“■”是換行符,你若是要打破什么鍋來(lái)問(wèn)我到底是怎么知道的話。我倒是會(huì)很樂(lè)意的告訴你:這就是經(jīng)驗(yàn)!偶從學(xué)習(xí)C#那刻起,就拿第一個(gè)Windows程序——記事本來(lái)開(kāi)刀,保存文檔時(shí)得來(lái)的經(jīng)驗(yàn)。
所以服務(wù)器讀出來(lái)的格式如下圖(http://blog.csdn.net/images/blog_csdn_net/cityhunter172/85935/r_aspxForm07.jpg):
5、在ASP.NET頁(yè)面發(fā)放Cookie
發(fā)送上述Cookie的.cs代碼為:
System.Web.HttpCookie ck=new HttpCookie("ckValue0");
ck["Author"]="CityHunter";
ck.Expires=System.DateTime.Now.AddMinutes(10);//若不指定,則為即時(shí)型Cookie
//ck.Path="/FormTest/ManageSys";//設(shè)置Cookie的虛擬路徑,注意一定要以“/”開(kāi)頭,否則為無(wú)效Cookie;請(qǐng)大家自行看一下它與在客房端的Cookie文檔“名稱(chēng)”與“Internet地址”的關(guān)系
Response.Cookies.Add(ck);
ck=newHttpCookie("ckValue1");//重新新建一個(gè)名為ckValue1的Cookie
ck.Expires=System.DateTime.Now.AddMinutes(20);//即刻起20分鐘后失效
ck["E_Mail"]="cityhunter172@126.com";//設(shè)置ckValue1中的E_Mail值
ck["PersonalWeb"]="172.meibu.com";
Response.Cookies.Add(ck);//添加此Cookie
6、取回已發(fā)放Cookie的值
Response.Write(Request.Cookies["ckValue0"]["Author"]+"<br>");//用不著說(shuō)明了吧
Response.Write(Request.Cookies["ckValue1"]["E_Mail"]+"<br>");
Response.Write(Request.Cookies["ckValue1"]["PersonalWeb"]);
好久沒(méi)有出作業(yè)啦(何出此言?),這第三篇呀,可是花了偶兩個(gè)星期的業(yè)余時(shí)間調(diào)試、總結(jié)、撰寫(xiě)哪,都說(shuō)時(shí)光貴如金,不知我花的這些時(shí)間能換來(lái)多少銀子?換銀子,我看是沒(méi)指望啦,能得到閣下的一句評(píng)論,偶也滿足了。記住,你的評(píng)論就是偶繼續(xù)寫(xiě)下去的動(dòng)力。
作業(yè):給Cookie賦于以下值,怎樣得到它的正確值
ck["str1"]="2222";
ck["str"]="str0=11111&str1=223";
可以肯定的是Request.Cookies["ckValue1"]["str"]得不到“str0=11111&str1=223”這個(gè)字串,大家不妨試一下Request.Cookies["ckValue1"]["str1"]會(huì)得到意想不到的字串喲。
提示:使用Server.UrlEncode()與Server.UrlDecode()
十三、發(fā)放永久性的驗(yàn)證Cookie
終于……終于……最后一個(gè)章節(jié),驀然回首,洋洋灑灑十二章。沒(méi)想到年少時(shí)寫(xiě)不完作文的偶,居然也能編出幾千余字的文章來(lái)呀,不得不佩服偶自己呀!再回首,一大片暈倒的人……。永遠(yuǎn)到底有多遠(yuǎn)?永久究竟是多久?只有天知道。
大家登錄CSDN的時(shí)候是否留意到一個(gè)“2周內(nèi)不用再登錄”的復(fù)選框,它又是怎么做到的呢?大家是否曾遇到過(guò)這樣的困惑:在執(zhí)行System.Web.Security.FormsAuthentication.SetAuthCookie時(shí)明明已指定createPersistentCookie為true為何關(guān)閉瀏覽器仍不能直接訪問(wèn)網(wǎng)站?下面我們就這個(gè)問(wèn)題給大家解釋一下,且介紹如何手工創(chuàng)建身份驗(yàn)證票并加入Cookie中。
System.Web.Security.FormsAuthenticationTicket tk=newSystem.Web.Security.FormsAuthenticationTicket(
1,//指定版本號(hào):可隨意指定
"Admin",//登錄用戶名:對(duì)應(yīng)Web.config中<allowusers="Admin"…/>的users屬性
System.DateTime.Now,//發(fā)布時(shí)間
System.DateTime.Now.AddYears(100),//失效時(shí)間:100年以后,夠永夠久了吧
false,//是否為持久Cookie:尚未發(fā)現(xiàn)有何用,至少目前偶還不知,下面會(huì)有說(shuō)明
"測(cè)試用戶數(shù)據(jù)"//用戶數(shù)據(jù):可用((System.Web.Security.FormsIdentity)User.Identity).Ticket.UserData獲取
);
stringstr=System.Web.Security.FormsAuthentication.Encrypt(tk);//加密身份驗(yàn)票
//聲明一個(gè)Cookie,名稱(chēng)為Web.config中<formsname=".APSX"…/>的name屬性,對(duì)應(yīng)的值為身份驗(yàn)票加密后的字串
System.Web.HttpCookieck=newHttpCookie(System.Web.Security.FormsAuthentication.FormsCookieName,str);
//指定Cookie為Web.config中<formspath="/"…/>path屬性,不指定則默認(rèn)為“/”
ck.Path=System.Web.Security.FormsAuthentication.FormsCookiePath;
//此句非常重要,少了的話,就算此Cookie在身份驗(yàn)票中指定為持久性Cookie,也只是即時(shí)型的Cookie關(guān)閉瀏覽器后就失效;因此上面我說(shuō):我是真的還不知在身份驗(yàn)票中指定為持久性Cookie有何用。
ck.Expires=System.DateTime.Now.AddYears(100);
Response.Cookies.Add(ck);//添加至客房端
后記
此系列文章共三部分,歷時(shí)一個(gè)月完成(2005-11-05~2005-12-06)。以上是我學(xué)習(xí)并用于實(shí)踐的一些經(jīng)驗(yàn),在此拿出來(lái)與大家一起分享。代碼都是經(jīng)過(guò)調(diào)試的,如有任何疑問(wèn),可在CSDN論壇(http://community.csdn.net/)找到我,我的ID是cityhunter172(可用此ID發(fā)短消息給我),昵稱(chēng)為寒羽楓,歡迎大家批評(píng)指正。
第四部分Form認(rèn)證的補(bǔ)充
前三篇在CSDN論壇公布后,效果如同“神仙放屁——果然不同凡(反)響”。為感謝廣大網(wǎng)友的熱情與支持,這不,經(jīng)過(guò)這一陣子的醞釀、修煉,特意準(zhǔn)備了這第四響。
之前我們講述的使用Form認(rèn)證實(shí)現(xiàn)單點(diǎn)登錄,正如網(wǎng)友所說(shuō)的那樣,只能在同一域名下使用。對(duì)于跨域名的單點(diǎn)登錄,除了使用Passport認(rèn)證外,我們還是可以用Form認(rèn)證的,只是要講究方法而已啦。正所謂“山不轉(zhuǎn)水轉(zhuǎn),人不轉(zhuǎn)心轉(zhuǎn)”。
一、跨域名的解決思路
在MSDN2003上搜索關(guān)鍵字“Passport”,偶找到一篇“Passport身份驗(yàn)證提供程序”。文章講述了Passport的認(rèn)證原理,共8條,我就不多說(shuō)了,大伙自個(gè)看吧。其中有一句話,引起偶的注意:“……響應(yīng)在查詢字符串中包含一個(gè)加密的Passport Cookie……”。也正是此句才有了下面的思路。
所謂認(rèn)證的通過(guò)與否,其實(shí)質(zhì)就是檢測(cè)有無(wú)發(fā)放有效的Cookie,使用Form也好,運(yùn)用Passport也罷,都是Cookie在起作用。也就是說(shuō),我們只要把有效的Cookie在登錄后一次性發(fā)放給客戶端就得了。
二、跨域名、跨服務(wù)器的單點(diǎn)登錄方法
1、如何在本機(jī)模擬跨域名、跨服務(wù)器的SingleSignOn
只要瀏覽網(wǎng)址不同就相當(dāng)于不同域名,在本機(jī)至少有以下三種。它們雖然是同一項(xiàng)目,彼此卻不能共用Session與Cookie,也就無(wú)法共享身份驗(yàn)證票:
a).http://localhost/FormTest/Login.aspx
b).http://127.0.0.1/FormTest/Login.aspx
c).http://My_Computer_Name/FormTest/Login.aspx//以電腦名稱(chēng)瀏覽站點(diǎn)
d).http://192.168.0.8/FormTest/Login.aspx//以網(wǎng)卡地址瀏覽站點(diǎn)
e).http://172.meibu.com/FormTest/Login.aspx//擁有國(guó)際域名
2、在ASP.NET中如何提交給其它頁(yè)面
用過(guò)ViewState的大概都知道,ViewState是保存在客戶端的。不知大伙注意沒(méi)有,ASP.NET為每張.aspx頁(yè)面都配備了獨(dú)自的ViewState,且被解析后都是以一個(gè)name="__VIEWSTATE"的隱藏控件值來(lái)保存ViewState。每次頁(yè)面提交,服務(wù)器都會(huì)檢查該控件的值有無(wú)被篡改,如此一來(lái)就注定.aspx只能提交給本頁(yè)。服務(wù)器是死的,人是活的,我們不能被這些條條框框限定死了,我們要把程序?qū)懗苫畹摹?
下面咱們從http://localhost/FormTest/Login.aspx輸入用戶名與密碼,然后提交給http://127.0.0.1/FormTest/Public/LoginTransfer.aspx。Login.aspx與LoginTransfer.aspx都包含用戶名輸入框一個(gè)、密碼輸入框一個(gè)、登錄按鈕一個(gè)。在Login.aspx頁(yè)面加入以下代碼:
this.Btn_Login.Attributes["onclick"]="SingleSignOn()";//指定執(zhí)行腳本事件
在Login.aspx頁(yè)面上插入以下腳本:
<script language="javascript">
Function SingleSignOn()
{
//只能用腳本改變指定Form提交的對(duì)象
document.getElementById("Form1").action="http://127.0.0.1/FormTest/Public/LoginTransfer.aspx?FromUrl="+window.location.href;
//把隱藏控件__VIEWSTATE中的值變更為L(zhǎng)oginTransfer.aspx解析后出現(xiàn)的值,以實(shí)際看到的值為準(zhǔn)
document.all.__VIEWSTATE.value="dDwtMTkyODUzMTMyNzs7Pv1cp2RaxUcr5hGYf8ILX9/EMKy8";
}
</script>
注意事項(xiàng)
a).LoginTransfer.aspx出現(xiàn)的控件及其ID,必須能夠在Login.aspx找到
b).控件的ID必須一致,且能一一對(duì)應(yīng)
c).關(guān)于__VIEWSTATE中的值,它與頁(yè)面控件ID無(wú)關(guān),與瀏覽該頁(yè)面的網(wǎng)址無(wú)關(guān),目前我只知道和控件的數(shù)量、類(lèi)型、名字空間(namespaceFormTest.Public)以及存在的ViewState有關(guān)系。大家在測(cè)試時(shí),以直接瀏覽http://127.0.0.1/FormTest/Public/LoginTransfer.aspx后,查看頁(yè)面源文件所看到的值為準(zhǔn)。
d).提交后,將觸發(fā)并執(zhí)行LoginTransfer.aspx中的Btn_Login_Click事件
3、基本思路
各個(gè)站點(diǎn)的登錄頁(yè)面統(tǒng)一將用戶名與密碼提交給LoginTransfer.aspx,同時(shí)各個(gè)站點(diǎn)需要一個(gè)增加Cookie的頁(yè)面,用于將加密后的身份驗(yàn)證Cookie添加至客戶端。此乃經(jīng)過(guò)一番考量后,最終確定的可行性方案。
4、第一種思路——天女散花
何謂天女散花,就是把Cookie在登錄后一次性全發(fā)放出去,就如同天仙在空中散花一樣,場(chǎng)面是何等的壯觀。下面開(kāi)始寫(xiě)代碼:
為更好的區(qū)分,我們將負(fù)責(zé)添加Cookie的頁(yè)面分開(kāi)命名:
a).http://localhost/FormTest/Public/AddCookie_A.aspx
b).http://127.0.0.1/FormTest/Public/AddCookie_B.aspx
c).http://My_Computer_Name/FormTest/Public/AddCookie_C.aspx
這三張頁(yè)面的功能一樣,所以代碼也就相同啰
privatevoidPage_Load(objectsender,System.EventArgse)
{
stringfrom=Request["FromUrl"];//起始URL路徑
stringnext=Request["NextUrl"];//還需要跳轉(zhuǎn)的URL
stringkey=Request["CookieTicket"];//已加密的Cookie文本
if(key!=null&&key!="")
{
System.Web.HttpCookieck=newHttpCookie(System.Web.Security.FormsAuthentication.FormsCookieName,key);
ck.Path=System.Web.Security.FormsAuthentication.FormsCookiePath;
ck.Expires=System.DateTime.Now.AddYears(100);
Response.Cookies.Add(ck);//將傳過(guò)來(lái)的已加密的身份驗(yàn)證票添加至客房端
stringurl=next.Split(';')[0];//從URL中拆分出將要跳轉(zhuǎn)的下一張頁(yè)面
next=next.Replace(url+";","");//帶入下一輪跳轉(zhuǎn)的字串
if(url!="")
{
//跳至下一頁(yè)面Response.Redirect(url+"?CookieTicket="+key+"&FromUrl="+from+"&NextUrl="+next);
}
else//已沒(méi)有下一頁(yè)面可供跳轉(zhuǎn)
{
Response.Redirect(from);//回到起始頁(yè)面
}
}
}
接下來(lái)編寫(xiě)LoginTransfer.aspx的代碼:
//頁(yè)面常量allLoginUrl存放所有站點(diǎn)的AddCookie.aspx的URL,注意以;分隔
publicconststringallLoginUrl=
"http://localhost/FormTest/Public/AddCookie_A.aspx;"
+"http://127.0.0.1/FormTest/Public/AddCookie_B.aspx;"
+"http://My_Computer_Name/FormTest/Public/AddCookie_C.aspx;";
偶已在上面講述了,如何點(diǎn)擊Login.aspx中的登錄按鈕Btn_Login將用戶名與密碼提交給LoginTransfer.aspx,并執(zhí)行LoginTransfer.aspx中的Btn_Login_Click事件。
privatevoidBtn_Login_Click(objectsender,System.EventArgse)
{
stringfrom=Request["FromUrl"];//起始URL路徑
stringnext=this.allLoginUrl;
//由于控件ID相同,所以此處得到的是由Login.aspx提交過(guò)來(lái)的用戶名與密碼
if(this.Txt_LoginName.Text=="Admin"&&this.Txt_Password.Text=="123456")
{
System.Web.Security.FormsAuthenticationTickettk=newSystem.Web.Security.FormsAuthenticationTicket(1,"Admin",System.DateTime.Now,System.DateTime.Now.AddYears(100),false,"測(cè)試用戶數(shù)據(jù)");
stringkey=System.Web.Security.FormsAuthentication.Encrypt(tk);//得到加密后的身份驗(yàn)證票字串
stringurl=next.Split(';')[0];//從URL中拆分出將要跳轉(zhuǎn)的下一張頁(yè)面
next=next.Replace(url+";","");//帶入下一輪跳轉(zhuǎn)的字串
Response.Redirect(url+"?CookieTicket="+key+"&FromUrl="+from+"&NextUrl="+next);//跳至下一頁(yè)面
}
}
5、第二種思路——后羿射日
后羿射日,意思指的是用戶點(diǎn)哪就跳哪。他若是點(diǎn)“火坑”,你也得往里跳,因?yàn)橛脩羰巧系勐铩N覀冊(cè)黾右粋€(gè)通行證頁(yè)面MyPassport.aspx,由http://127.0.0.1/FormTest/Public/LoginTransfer.aspx發(fā)放驗(yàn)證Cookie后直接跳轉(zhuǎn)至http://127.0.0.1/FormTest/MyPassport.aspx。不要告訴我你不會(huì),你要是真不會(huì),那偶也沒(méi)法子啦,還得請(qǐng)你回頭看看,偶在第三篇是如何講述發(fā)放永久性驗(yàn)證Cookie吧(http://blog.csdn.net/cityhunter172/archive/2005/12/06/545301.aspx)。還需要一張用作跳板的跳轉(zhuǎn)頁(yè)面MyTransfer.aspx。
MyPassport.aspx的代碼:
<atarget="_blank"
href="MyTransfer.aspx?goto=http://localhost/FormTest/Public/AddCookie_D.aspx">
美麗的天使</a>
<atarget="_blank"
href="MyTransfer.aspx?goto=http://127.0.0.1/FormTest/Public/AddCookie_E.aspx">
快樂(lè)的天堂</a>
<atarget="_blank"
href="MyTransfer.aspx?goto=http://My_Computer_Name/FormTest/Public/AddCookie_F.aspx">
大大的火坑</a>
MyTransfer.aspx的代碼:
privatevoidPage_Load(objectsender,System.EventArgse)
{
//獲取身份驗(yàn)證票
System.Web.Security.FormsAuthenticationTickettk=((System.Web.Security.FormsIdentity)User.Identity).Ticket;
stringkey=System.Web.Security.FormsAuthentication.Encrypt(tk);//每次加密后的字串都是不同的
stringnext=Request["goto"];//將要跳轉(zhuǎn)的URL
Response.Redirect(url+"?CookieTicket="+key);//跳轉(zhuǎn)至下一頁(yè)面
}
AddCookie_D.aspx、AddCookie_E.aspx、AddCookie_F.aspx這三張頁(yè)面的代碼:
stringkey=Request["CookieTicket"];//已加密的Cookie文本
if(key!=null&&key!="")
{
System.Web.HttpCookieck=newHttpCookie(System.Web.Security.FormsAuthentication.FormsCookieName,key);
ck.Path=System.Web.Security.FormsAuthentication.FormsCookiePath;
ck.Expires=System.DateTime.Now.AddYears(100);
Response.Cookies.Add(ck);//將傳過(guò)來(lái)的已加密的身份驗(yàn)證票添加至客房端
Response.Redirect("../Index.aspx");//跳轉(zhuǎn)至你真正想帶客戶去的地方
}
6、點(diǎn)評(píng)
兩者共同點(diǎn):
a).每個(gè)站點(diǎn)都需要一個(gè)登錄的提交點(diǎn)、一張?zhí)砑覥ookie的頁(yè)面。
b).因?yàn)橹荒芸堪l(fā)放驗(yàn)證Cookie來(lái)識(shí)別身份,所以一臺(tái)電腦不能同時(shí)登錄兩個(gè)帳號(hào)。
c).都存在不同程度的安全隱患。
兩者不同點(diǎn):(天女散花以下簡(jiǎn)稱(chēng)“開(kāi)女”,后羿射日就簡(jiǎn)稱(chēng)“后羿”)
a).天女一次性發(fā)放Cookie,如果站點(diǎn)較多,處理起來(lái)還是需要一些時(shí)間的。而后羿則相反,站點(diǎn)再多也不怕。
b).天女在散花的過(guò)程中,如果中途被卡住,則需要一個(gè)錯(cuò)誤處理機(jī)制做回退處理。后羿則不需要。
c).天女在登錄后可以直接在IE地址瀏覽其想看的站點(diǎn);而后羿則必須從通行證的跳板頁(yè)面進(jìn)入才行。
根據(jù)上述問(wèn)題,給幾點(diǎn)建議:
a).不要使用永久性Cookie,應(yīng)指明身份驗(yàn)證票的過(guò)期時(shí)間,注意不是Cookie的有效期。
b).在身份驗(yàn)證票的UserData中加入其它的驗(yàn)證信息或存放用戶ID
c).在網(wǎng)絡(luò)通暢的情況下,比如局域網(wǎng),站點(diǎn)又相對(duì)較少,建議選用天女。50個(gè)站點(diǎn)之間做跳轉(zhuǎn)應(yīng)該不會(huì)超過(guò)10秒(前提是已編譯好了,且不是初次訪問(wèn))。
三、跨域名、跨服務(wù)器的退出方法
只要理解了“天女散花”,退出就比較容易啦。為每個(gè)站點(diǎn)準(zhǔn)備一個(gè)用于退出的頁(yè)面,如下:
a).http://localhost/FormTest/Public/Logout.aspx
b).http://127.0.0.1/FormTest/Public/Logout.aspx
c).http://My_Computer_Name/Public/FormTest/Logout.aspx
privatevoidPage_Load(objectsender,System.EventArgse)
{
System.Web.Security.FormsAuthentication.SignOut();//刪除Cookie中的身份驗(yàn)證票
stringfrom=Request["FromUrl"];
stringnext=Request["NextUrl"];
stringurl=next.Split(';')[0];
next=next.Replace(url+";","");
if(url!="")
{
Response.Redirect(url+"?FromUrl="+from+"&NextUrl="+next);
}
else
{
Response.Redirect(from);
}
}
轉(zhuǎn)載于:https://www.cnblogs.com/yexinw/archive/2011/09/15/2178134.html
總結(jié)
- 上一篇: ktv多少钱一小时啊?
- 下一篇: qt 试用 (3)配置编译源代码及调试