Express教程05:Cookie

閱讀更多系列文章請訪問個人GitHub博客,示例代碼請訪問這裏

Cookie介紹

Cookie存儲在瀏覽器,在瀏覽器請求服務器時,其中的數據都會被髮送到服務端,經常使用來作用戶信息校驗等。html

但因爲Cookie存儲在瀏覽器,容易受到篡改,安全性較差。前端

使用cookie-parser處理Cookie

處理Cookie,可使用中間件cookie-parsergit

讀取Cookie

示例代碼:/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"}瀏覽器

設置Cookie

示例代碼:/lesson05/server.js安全

設置Cookie能夠用Express自帶的方法res.cookiebash

方法的第一個參數爲設置的屬性名,第二個參數爲屬性值,第三個參數爲配置項,例如:服務器

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天。

Cookie的簽名

示例代碼:/lesson05/server.js

Cookie的簽名便是使用一個存儲在服務端的密鑰對Cookie進行加密,Cookie中存儲的數據是通過密鑰加密的,所以客戶端若是對Cookie進行修改,服務端校驗就沒法經過。

設置密鑰

若須要給Cookie進行簽名,首先須要給cookieParser的第一個參數傳入一個字符串密鑰:

// 解析Cookie
server.use(cookieParser(
  // 簽名用密鑰,須要保密,僅存儲在服務端
  'NpLRTpy1vbBzEw2JcAxpf970kOk2RViDn5wKwrMv'
))
複製代碼

簽名Cookie

這樣就能夠開始設置簽名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

其意義以下:

  1. s表示該Cookie爲簽名Cookie
  2. test123表示該Cookie設置的值
  3. HrZ44MCUeLXj0uZAzTpCXWduflOsmfBs5XsuK4eTMvg表示對該值的簽名,也就是說當服務端接收到該Cookie時,會使用服務端的密鑰對test123進行簽名,再與HrZ44MCUeLXj0uZAzTpCXWduflOsmfBs5XsuK4eTMvg進行對比,若是正確纔可使用。

此時能夠看到服務端打印結果爲signedCookies: {"password":"test123"}

在客戶端修改簽名的Cookie

若是用戶在客戶端對簽名的Cookie進行了修改,例如在瀏覽器控制檯,將password改成s%3Atest456.HrZ44MCUeLXj0uZAzTpCXWduflOsmfBs5XsuK4eTMvg

此時在服務端打印的結果爲signedCookies: {"password":false},表示校驗失敗。

同時瀏覽器中的Cookie值被從新修改成了s%3Atest123.HrZ44MCUeLXj0uZAzTpCXWduflOsmfBs5XsuK4eTMvg

除非用戶在修改簽名的Cookie的值時,將該值的簽名一塊兒修改,不然校驗是沒法經過的。

但因爲簽名是由服務端的密鑰計算而成,所以這個值一般是安全的。

不過,由於對Cookie進行簽名,會佔用更多的Cookie存儲空間,而Cookie在瀏覽器中最多隻能存儲4K,因此簽名不可濫用,只用來保護重要的數據便可。

相關文章
相關標籤/搜索