鬼打牆事件之『ASP.NET 無法刪除 Cookie 的問題』

先將我的執行環境說明一下:

  • 我有兩個網站,網域分別為 www1.domain.com 與 www2.domain.com
  • 自己實做單一簽入(Single Sign On, SSO)的機制,並透過 Web Service 進行網站會員登入、登出
  • 兩個網站共用同一組 Cookie 用以儲存 SSO 的 Token,且明訂 Cookie 的 Domain 為 .domain.com

我今天聚焦在「登出」這個簡單的功能就好,實作登出是在簡單不過的機制了,就是把 Cookie 清除掉就好啦!不過要是跟我一樣遇到 ASP.NET 怎樣也清除不掉 Cookie 的情況,那就真的是「鬼打牆」了,而且若要問人家:「請問 Cookie 要怎麼樣才能刪除掉?」這種問題問別人真的會被笑,也不知道怎麼開口。

因為我要共用 Cookie 在兩個網域,所以我的 Cookie Domain 是 .domain.com,所以照理說清除 Cookie 的方法應該是:

Response.Cookies["Token"].Expires = DateTime.Now.AddYears(-1);

或者是

Response.Cookies["Token"].Expires = DateTime.Now.AddYears(-1);
Response.Cookies["Token"].Domain = ".domain.com";

或者是

Response.Cookies["Token"].HttpOnly = true;
Response.Cookies["Token"].Expires = DateTime.Now.AddYears(-1);
Response.Cookies["Token"].Domain = ".domain.com";

反正能試的都試了,而且以我對 HTTP 底層協定的了解,幾乎在 Web 領域沒有什麼問題是無法解決的,但今天遇到 Cookie 清不掉這個問題,真的讓我滿面愁容,程式越寫越氣,用 Fiddler2 看 HTTP 封包看了幾十遍,就是看不出有任何問題,但 Cookie 就是殺不掉。

但是這問題非得要研究出來不可,就因為這個「無法登出」的「小問題」搞了我快 5 個小時才弄清楚所有來龍去脈,所幸問題有被我追根究柢的解決了,以下是要解決此問題的完整解法:

  • 若要清除跨 Domain 的 Cookie 必須清除兩次,例如說使用者在 www1.domain.com 要執行登出動作,必須要先將 Domain 為 www1.domain.com 的 Cookie 給清除掉,在接著將 Domain 為 .domain.com 的這個 Cookie 清除掉。
  • 因為這兩個 Cookie 為「同名」,全部都叫做 Token,所以無法在一個 HTTP Request 中清除掉兩個同名的 Cookie,所以必須要在不同的兩個 HTTP Request 中個別刪除不同 Domain 的 Cookie。

例如說:你必須先連到 Logout.aspx 頁面,在此頁面先將第一組 Cookie 清除:

HttpCookie cookie = new HttpCookie("Token", ""); 

cookie.HttpOnly = true;
cookie.Expires = DateTime.Now.AddYears(-1); 
cookie.Domain = Request.Url.Host;
Response.SetCookie(cookie);

Response.Redirect("Logout2.aspx", true);

然後再轉址到 Logout2.aspx 將 Parent Domain 的 Cookie 給清除掉:

HttpCookie cookie = new HttpCookie("Token", ""); 

cookie.HttpOnly = true;
cookie.Expires = DateTime.Now.AddYears(-1); 
cookie.Domain = ".domain.com";
Response.SetCookie(cookie);

Response.Redirect("index.aspx", true);

這樣就可以徹底將 Cookie 給清乾淨了,這真是難得的經驗,從沒想到有這種解法,不知道網路上有沒有其他人遇過跟我同樣的問題?

而我的登出程式最後是改成以下這段 Code,濃縮再一支程式裡:

protected void Page_Init(object sender, EventArgs e)
{
    Response.Cache.SetCacheability(HttpCacheability.NoCache); 

    HttpCookie cookie = new HttpCookie("Token", ""); 

    cookie.HttpOnly = true;
    cookie.Expires = DateTime.Now.AddYears(-1); 

    if (Request.QueryString["domain"] == null)
    {
        cookie.Domain = Request.Url.Host;
        Response.SetCookie(cookie);
        Response.Redirect("Logout.aspx?domain=1"), true);
    }
    else
    {
        cookie.Domain = ".domain.com";
        Response.SetCookie(cookie);
        Response.Redirect("index.aspx", true);
    } 
}
  

此文章由 will 發表於 2008/6/4 下午 08:44:02

永久連結 | 評論 (6) | 此文章的RSSRSS comment feed |

分類: .Net | ASP.NET | C# | Web | 心得分享

標籤: , , ,

收藏:

相關文章

評論

六月 4. 2008 22:29

chihwen

看文中沒有提到 path 這個參數...
會不會是 cookie 中的 path 參數沒有正確設定造成的?
在刪除cookie時,需跟建立cookie時,設定相同的path才行。
若在建立cookie時,沒有特別指定path,則path的預設值就是cookie被建立時的當前路徑。

chihwen tw

六月 4. 2008 22:34

chihwen

看文中沒有提到 path 參數,會不會是這個參數沒有正確指定所致?

chihwen tw

六月 5. 2008 00:16

will

我所有程式都是放在根目錄的,所以應該跟 Cookie Path 無關。

will tw

六月 5. 2008 10:18

Weber 凱淵爸爸

好站耶,版主很用心,我一定常常來逛的!
加油!

Weber 凱淵爸爸 tw

六月 5. 2008 10:21

will

感恩啦! ^_^

will tw

八月 14. 2008 10:39

bruce

小弟大膽的做了個實驗,Session 清除成功,但 Cookies 清除失敗!
想請教版主,我是否哪作錯了?!
---------------------------------------------------
protected void INOUT(object sender, EventArgs e)
{
if (IsPostBack )
{
if (Session["aaa"] == null)
{
Session["aaa"] = "Show youself";
Response.Cookies["user_id"]["UID"] = "abcdefg";
Response.Write(Session["aaa"] + "<br />");
Response.Write(Request.Cookies["user_id"]["UID"] + "<br />");

}
else
{
//Session["aaa"] = "";
//Session.Clear();
//Session.Abandon();
//Session.RemoveAll();
Session.Remove("aaa");
//Response.Cookies["user_id"].Values.Remove("UID");
//Response.Cookies["user_id"].Expires = DateTime.Now.AddYears(-1);

HttpCookie cookie = new HttpCookie("user_id", "UID");
cookie.HttpOnly = true;
cookie.Expires = DateTime.Now.AddYears(-1);
cookie.Domain = Request.Url.Host;
Response.SetCookie(cookie);

Response.Write(Session["aaa"] +"<br />");
Response.Write(Request.Cookies["user_id"]["UID"] + "<br />");

}

}

}

bruce tw

新增評論


(將顯示您的Gravatar圖示)  

  Country flag

[b][/b] - [i][/i] - [u][/u]- [quote][/quote]



線上預覽

八月 29. 2008 11:13