上篇介紹了註冊的基本流程,下篇簡單的講講登入的流程以及Cookie的出現
實現登入的小功能
當你在瀏覽器的輸入框裡輸入localhost:8080/sign_in
的時候,會發起GET
請求,去訪問sign_in.html
if (path === `/sign_up` && method === `GET`) {
let string = fs.readFileSync(`./sign_up.html`, `utf8`)
response.statusCode = 200
response.setHeader(`Content-Type`, `text/html;charset=utf-8`)
response.write(string)
response.end()
}
複製程式碼
CSS佈局與上篇的佈局基本一樣,略去不表~
比對使用者的資訊與資料庫裡面的資訊是否匹配
依然是上篇的套路,獲得使用者formdata後,分析資料,和資料庫裡面的比對
var users = fs.readFileSync(`./db/users`, `utf8`)
try {
users = JSON.parse(users) //[] JSON也支援陣列
} catch (exception) {
users = []
}
let found
for (let i = 0; i < users.length; i++) {
if (users[i].email === email && users[i].password === password) {
found = true
break
}
}
if (found) {
response.setHeader(`Set-Cookie`, `sign_in_email=${email};HTTPOnly`)
response.statusCode = 200
} else {
response.statusCode = 401
}
複製程式碼
不同的是引入了一個header
,也就是今天的主角–Cookie
其實這和平常上網的情形類似的,有時候我們訪問一些購物網站,並沒有登入,但是你在購物車裡面新增東西了,當你逛了以後再回來的時候,發現購物車裡面有你的記錄,幫你做這個事的也是cookie。
因為HTTP協議是無狀態的,即伺服器不知道使用者上一次做了什麼,這嚴重阻礙了互動式Web應用程式的實現。在典型的網上購物場景中,使用者瀏覽了幾個頁面,買了一盒餅乾和兩瓶飲料。最後結帳時,由於HTTP的無狀態性,不通過額外的手段,伺服器並不知道使用者到底買了什麼,所以Cookie就是用來繞開HTTP的無狀態性的“額外手段”之一。伺服器可以設定或讀取Cookies中包含資訊,藉此維護使用者跟伺服器會話中的狀態。
可以看出,當你在sign_in發起GET
請求並設定了Set-Cookie
之後,其他的同源的頁面,又都會帶上Cookie
,也就能保證同源的網頁向伺服器發起請求的時候,伺服器能夠明白,你己經是登入的使用者了,與那些沒有拿到cookie的頁面區別開來。
Cookie的入門
為什麼要在cookie裡面寫上HttpOnly
呢,因為這個可以防止有些牛人使用JS
修改Cookie的內容。
- 如果不寫這個的話,可以使用
js
修改的
寫了HttpOnly
之後將無法修改
_ga是啥
這個是Chrome的功能,用於分析cookie的
每一部分的作用詳見這裡
Cookie的特點
通過上述的例子,可以總結幾點重要的特點
- 伺服器通過 Set-Cookie 響應頭設定 Cookie
- 瀏覽器得到 Cookie 之後,每次請求都要帶上 Cookie
- 伺服器讀取 Cookie 就知道登入使用者的資訊(email)
當然了,還有幾個問題需要解答一下。
- Cookie 存在哪
存在硬碟的一個檔案裡面 - Cookie會被使用者篡改嗎?
可以,也就是說它並不安全的。
- Cookie 有效期嗎?
預設有效期20分鐘左右,不同瀏覽器策略不同
後端可以強制設定有效期
Set-Cookie: <cookie-name>=<cookie-value>; Expires=<date>
Set-Cookie: <cookie-name>=<cookie-value>; Max-Age=<non-zero-digit>
複製程式碼
具體語法看 Set-Cookie
使用者登入後,首頁顯示不同
既然你成功登入,理應跳轉到首頁,並顯示相應的介面。
$.post(`/sign_in`, hash)
.then((response) => {
window.location.href = `/`
},
(request) => {
alert(`郵箱與密碼不匹配`)
}
)
複製程式碼
然後首頁的資訊應該根據使用者資訊做出相應的變化
let cookies = request.headers.cookie.split(`; `) //[`email=..@..`, `a=1`]
let hash = {}
cookies.forEach((cookie) => {
let parts = cookie.split(`=`)
let key = parts[0]
let value = parts[1]
hash[key] = value
})
let email = hash.sign_in_email
let users = fs.readFileSync(`./db/users`, `utf8`)
users = JSON.parse(users)
let foundUser
for (let i = 0; i < users.length; i++) {
if (users[i].email === email) {
foundUser = users[i]
break
}
}
if (foundUser) {
string = string.replace(`email`, foundUser.email)
} else {
string = string.replace(`恭喜,email你已成功登入`, `沒有該使用者`)
}
複製程式碼
這裡的程式碼邏輯與上篇的基本一致,唯一的不同在於第一行程式碼
let cookies = request.headers.cookie.split(`; `) //[`email=..@..`, `a=1`]
為什麼用;
字元來分割呢,這是因為可以有多個cookie
Cookie的兩個作用
一般來說常見的作用有如下兩個:
- 識別使用者的身份。當使用者A去訪問
localhost:8080
的時候,伺服器會給A一個獨一無二的id=00A
(這就是cookie),當使用者A訪問localhost:8080
的其他網頁的時候,都會帶著那個獨一無二的id。當B使用者來訪問localhost:8080
的時候,伺服器發現他沒有任何標識,也會給他一個獨一無二的id=00B
,所以藉助cookie伺服器端就能夠分清楚誰是誰了。 - 記錄你的瀏覽歷史。最常見的需求就是你去逛購物網站,你新增到購物車裡面的東西過幾天一定會在,而不會憑空消失了。例如A使用者去
taobao.com
去買點東西,新增了一個熱水壺、一部小米手機到購物車裡面,那麼伺服器端可以改寫你上面的cookie使之具體化「id=00A; cart=A1,A2」,表示你購物車裡面買了倆東西。你過幾天想起來了,去購物車裡面看,熱水壺、小米手機還在裡面。瀏覽器並不會刪除你存到硬碟上的cookie。
一張圖總結註冊登入的過程
接下來可以去搞一搞其他的,像什麼session
LocalStorage
……(@ο@) 哇~
程式碼連結sign_in.html