不知不覺這篇寫完就剩下10天了,雖然每次都會在螢幕前面發呆,想著等等要寫的內容
今天要來聊聊 cookie
、session
。
還記得以前要註冊會員還是玩網頁遊戲的時候,下方都會出現:「如果出現錯誤請先清除 cookie
後再試」,然後就很直觀的把 cookie
聯想成餅乾,也不知道它是幹嘛的XD
本文開始
在開發網頁時,要有一個很重要的觀念,那就是 HTTP 協定是無狀態的
。
這是什麼意思?
「簡單來說就是伺服器處理完你的 request 之後就與你無關了,而且它也不會記得你和它之間的故事,你們的關係形同陌生人,殘忍的是你又看著它與其他人展開新的故事,寫 code 再苦,也比不上它在你心中留下的傷痛,恨自己到底為什麼,直到現在還守著這份回憶,好似期待有一天還能夠回到當初,好想再看到那個屬於自己的微笑,只要一次就好,我真的...真的好想妳。」
打著打著眼淚沒有流出來,只是口有點渴而已。
蛤? 你說你正要按下檢舉?
等等,拜託不要檢舉我涉嫌文章灌水混字數,我馬上進入重點...
好啦,我們把故事改成這樣好不好,
「下班好累,開個臉蘇看廢文,聽說最近上面的年輕人越來越少了,咦!怎麼要我打帳密登入,我不是昨天才登入過,我的密碼抄在小紙上面,那張紙不知道跑去哪裡了,而且不對吧,這個使用者體驗是怎麼回事,每天打帳密就飽了!」
這個就是 HTTP 無狀態
特性,伺服器並不會知道你之前做了什麼,常見的例子還有購物車,買了好幾個商品要結帳,結果伺服器不知道我到底買了什麼。
cookie
可以用來解決這個問題,它能夠儲存一些資訊,像是我拿著會員卡,就能夠直接進入商店,因為上面的卡號說明了我是這家店已經付費過的客人,也就是他們的會員,所以我不用再付費就能夠入場。
以下是 cookie
的特性,
cookie
可能會浪費流量、或是帶上無用之 cookie
。cookie
。那什麼是 session
呢?
比較不嚴謹的解釋是,可以把 session
當成 server 版的 cookie
,那什麼時候又會用到呢?
舉回我們剛剛的例子,如果我們把辨識用戶登入的 cookie
這樣寫,
username=Bob;isLogin=true;
看起來沒問題啊,我後端收到這個 cookie
,我知道他是誰,而且已經登入過,cookie
也還沒過期,所以就不用讓他打帳密,直接進入使用者畫面。
但是請記得 cookie
是儲存在用戶端的,而且是明文,所以我把 cookie
直接改成
username=Alice;isLogin=true;
那我不就可以登入查看 Alice 的資料了嗎...?
所以才需要搭配使用 session
。
流程大概是這樣:
=> 使用者登入
=> 後端驗證後建立 session
,紀錄該用戶已登入
=> 接著回傳寫著這個 session
的 ID 的 cookie
=> 日後進入網站時,後端收到帶著 session ID
的 cookie
,然後查找這個 session
的資訊,發現已經登入
=> 讓使用者不用輸入帳密就登入網站
也有可能是不帶 session ID
的方法:
=> 使用者登入
=> 後端驗證後,設置一個寫著加密字串的 cookie
=> 日後進入網站時,後端解密這個字串,辨別用戶身分與維持登入狀態
但不管是哪種作法,原理都是把用戶 cookie
帶上的「東西」拿來查詢驗證。
「就像是我從事一個秘密交易,我透過轉帳付款,然後賣家給我一串亂碼,我只需要拿著這串亂碼,就能夠到指定地點取貨,而交貨者只需要把這段亂碼輸入他們的系統查詢,就能夠驗證我的個人資訊以及是否付款,而且我也不知道這串亂碼的規則,所以不能自己編造一個亂碼去取貨。」
講了那麼多,我們來看看怎麼使用 JS 操作 cookie
。
document.cookie;
// EX: username=Bob; age=18;
cookie
說穿了就是 key=value
的形式而已,但是我們剛剛透過 document.cookie
查看時,發現它們全部被組成字串,如果我只是要單純存取某個屬性的值而已,不就還要自己切割字串嗎?
沒錯! 還真的要自己切割字串, JS 本身沒有提供這些方法,所幸 W3C 有附上常用操作的函數,那就讓我們來看看吧。
function getCookie(cname) {
var name = cname + "=";
var decodedCookie = decodeURIComponent(document.cookie);
var ca = decodedCookie.split(';');
for(var i = 0; i <ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return "";
}
EX: 我想要取得 username
,就可以這樣寫,找到就會回傳,沒找到就回傳 ""
。
var myName = getCookie("username"); // Bob
function setCookie(cname, cvalue, exdays) {
var d = new Date();
d.setTime(d.getTime() + (exdays*24*60*60*1000));
var expires = "expires="+ d.toUTCString();
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
}
EX: 我想設置紀錄身高的 cookie
,
setCookie("height", 180);
其實有更方便的工具來操作/查看 cookie
,像是瀏覽器內建的開發者工具,
可以一目瞭然所有的 Name、Value、Domain、Path、Expires、HTTP。
這邊有注意到嗎,上面有一個 HTTP Only
、Secure
,它們分別代表的意思是
HTTP Only
: 設定的話 cookie
只能被 server 端存取,無法在用戶端存取,也就是設定的話沒辦法透過 JS 去操作它。Secure
: cookie
只允許在 HTTPS 下傳輸。那今日的分享就到這,我們明天見