Cookie存儲在瀏覽器,在瀏覽器請求服務器時,其中的數據都會被髮送到服務端,經常使用來作用戶信息校驗等。html
但因爲Cookie存儲在瀏覽器,容易受到篡改,安全性較差。前端
處理Cookie,可使用中間件cookie-parsergit
示例代碼:/lesson05/server.jsgithub
使用cookie-parser中間件時,須要先經過server.use(cookieParser())
解析cookie,以後就能夠在req.cookies
屬性中讀取到cookie的值。express
在瀏覽器打開http://localhost:8080/cookie,在控制檯寫入cookie{"userName":"lee"}
。api
// 使用cookie-parser中間件,解析Cookie
server.use(cookieParser())
server.get('/cookie', (req, res, next) => {
// 讀取cookieParser解析的Cookie
console.log(req.cookies)
res.send(`cookies: ${JSON.stringify(req.cookies)}`)
})
複製代碼
在瀏覽器打開http://localhost:8080/cookie,服務端打印結果爲:{"userName":"lee"}
。瀏覽器
示例代碼:/lesson05/server.js安全
設置Cookie能夠用Express自帶的方法res.cookie。bash
方法的第一個參數爲設置的屬性名,第二個參數爲屬性值,第三個參數爲配置項,例如:服務器
server.get('/cookie', (req, res, next) => {
// express自帶的設置Cookie方法
res.cookie('userName', 'lee', {
// 設置該Cookie只能夠由服務端訪問,即前端JavaScript沒法訪問document.cookie獲取該值,但控制檯仍是能夠查看和修改
httpOnly: true,
// 只有經過HTTPS請求的Cookie才被使用,不然都認爲是錯誤的Cookie
// secure: true,
// 設置保存Cookie的域名,瀏覽器查找Cookie時,子域名(如translate.google.com)能夠訪問主域名(google.com)下的Cookie,而主域名(google.com)不能夠訪問子域名(如translate.google.com)下的Cookie
// 本地測試可直接設置爲localhost
domain: 'localhost',
// 設置保存Cookie的路徑,瀏覽器查找Cookie時,子路徑(如/map)能夠訪問根路徑('/')下設置的Cookie,而根路徑('/')沒法訪問子路徑(如/map)下設置的Cookie
path: '/',
// 經過expires設置Cookie過時時間爲14天后
// expires: new Date(new Date().getTime() + 14 * 86400000),
// 經過maxAge設置Cookie過時時間爲14天后
maxAge: 14 * 86400000,
})
// 讀取cookieParser解析的Cookie
console.log(req.cookies)
res.send(`cookies: ${JSON.stringify(req.cookies)}`)
})
複製代碼
在瀏覽器的控制檯中,能夠看到設置的Cookie爲{"userName":"lee"}
,有效期是14天。
示例代碼:/lesson05/server.js
Cookie的簽名便是使用一個存儲在服務端的密鑰對Cookie進行加密,Cookie中存儲的數據是通過密鑰加密的,所以客戶端若是對Cookie進行修改,服務端校驗就沒法經過。
若須要給Cookie進行簽名,首先須要給cookieParser的第一個參數傳入一個字符串密鑰:
// 解析Cookie
server.use(cookieParser(
// 簽名用密鑰,須要保密,僅存儲在服務端
'NpLRTpy1vbBzEw2JcAxpf970kOk2RViDn5wKwrMv'
))
複製代碼
這樣就能夠開始設置簽名Cookie了,只須要在res.cookie
方法的配置參數中設置signed: true
屬性:
res.cookie('password', 'test123', {
httpOnly: true,
domain: 'localhost',
path: '/',
maxAge: 14 * 86400000,
// 開啓該Cookie的簽名模式
signed: true
})
複製代碼
在瀏覽器打開http://localhost:8080/cookie,能夠看到Cookie中被設置了password
屬性,其值爲s%3Atest123.HrZ44MCUeLXj0uZAzTpCXWduflOsmfBs5XsuK4eTMvg
。
若是用decodeURIComponent方法進行解碼,結果爲s:test123.HrZ44MCUeLXj0uZAzTpCXWduflOsmfBs5XsuK4eTMvg
。
其意義以下:
s
表示該Cookie爲簽名Cookietest123
表示該Cookie設置的值HrZ44MCUeLXj0uZAzTpCXWduflOsmfBs5XsuK4eTMvg
表示對該值的簽名,也就是說當服務端接收到該Cookie時,會使用服務端的密鑰對test123
進行簽名,再與HrZ44MCUeLXj0uZAzTpCXWduflOsmfBs5XsuK4eTMvg
進行對比,若是正確纔可使用。此時能夠看到服務端打印結果爲signedCookies: {"password":"test123"}
。
若是用戶在客戶端對簽名的Cookie進行了修改,例如在瀏覽器控制檯,將password改成s%3Atest456.HrZ44MCUeLXj0uZAzTpCXWduflOsmfBs5XsuK4eTMvg
。
此時在服務端打印的結果爲signedCookies: {"password":false}
,表示校驗失敗。
同時瀏覽器中的Cookie值被從新修改成了s%3Atest123.HrZ44MCUeLXj0uZAzTpCXWduflOsmfBs5XsuK4eTMvg
。
除非用戶在修改簽名的Cookie的值時,將該值的簽名一塊兒修改,不然校驗是沒法經過的。
但因爲簽名是由服務端的密鑰計算而成,所以這個值一般是安全的。
不過,由於對Cookie進行簽名,會佔用更多的Cookie存儲空間,而Cookie在瀏覽器中最多隻能存儲4K,因此簽名不可濫用,只用來保護重要的數據便可。