如何在node和vue以axios作為互動的專案中使用cookie或者set-cookie
最近在用vue+node+mysql重構專案,前端用的vue+typescript寫的,後端用的express框架,沒有用太多的外掛,用原始擼的。
專案地址https://github.com/Vitaminaq/node-mysql 歡迎交流。
剛好有個登陸頁面,為了儲存使用者資訊,必須得使用token。之前的思維一直侷限在,使用者登陸時,生成token,並用放在data裡面返回來,客戶端自己去儲存,需要驗證的頁面把token放在請求的headers的authorization欄位裡面,後端每次去讀這個欄位就可以驗證了,但是總感覺有點繁瑣。樣本我也貼一下吧,token我是用的jwt來生成的,至於存在哪裡,瀏覽器那幾種方法都還可以。
// 前端程式碼
axios.create({
baseURL: 'http://127.0.0.1:3005',
timeout: 5000,
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'no-cache',
'authorization': window.sessionStorage.getItem('token')
}
});
後面想到了響應頭裡面有個set-cookie欄位,非常的簡便,因為是全自動的,伺服器自動把資訊存入瀏覽器的cookie裡面,用來記錄驗證資訊非常方便。原生node的語法大致如下:
res.setHeader('Set-Cookie', [`token = ${token};path: '/'; secure: false; signed: false,userId = 1`]);
如果有多個欄位,第二個引數可以是陣列,結構就是key=value,後面跟一些對cookie配置的屬性。
domain | String | Cookie的域名。預設為應用程式的域名 |
encode | Function | 用於cookie值編碼的同步函式。預設為encodeURIComponent 。 |
expires | Date | GMT中cookie的到期日。如果未指定或設定為0,則建立會話cookie |
httpOnly | Boolean | 標記cookie只能由Web伺服器訪問。 |
maxAge | Number | 方便的選項,用於設定相對於當前時間的到期時間(以毫秒為單位)。 |
path | String | Cookie的路徑。預設為“/” |
secure | Boolean | 將cookie標記為僅與HTTPS一起使用。 |
signed | Boolean | 指示cookie是否應該簽名。 |
sameSite | Boolean or String | “SameSite” Set-Cookie屬性的值。更多資訊,請訪問https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site-00#section-4.1.1。 |
這些引數基本是用不太到的,但是大家可以去研究下,有個時候可以會涉及到cookie共享,各級域名間的共享等,就不多提了,世界之大,真要研究,好玩的太多了,一樣東西都能腿玩年。
express的語法大概如下(配置欄位跟上面是一樣的):
// 差不多就是把原生的拆成了單個的,看起來比較清晰。key, value, options,多個值的時候需要多行書寫。
res.cookie('token', token, { path: '/', secure: false, signed: false });
res.cookie('nickname', nickname, { path: '/', secure: false, signed: false });
光設定這個是不夠的,因為不屬於跨域共享資源,所以需要一些設定的支援,客戶端由於用了axios,就只說下axios吧。
在它官網上有個詳細的請求頭引數配置,裡面有一個withCredentials欄位,大概配置如下:(對於非axios的,其實也差不多,axios只不過是基於http的封裝,萬變不離其宗,把這個欄位加在你的請求頭裡就ok了)
axios.create({
baseURL: 'http://127.0.0.1:3005',
timeout: 5000,
withCredentials: true, //表示跨域請求時是否需要使用憑證,預設為false
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'no-cache'
}
});
node端也需要進行該配置,大概如下:
app.all('*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "http://127.0.0.1:8088");
res.header("Access-Control-Allow-Headers", "Content-Type, authorization, Cache-Control");
res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
res.header('Access-Control-Allow-Credentials', 'true'); // 就是這個欄位
next();
});
該欄位可選。它的值是一個布林值,表示是否允許傳送Cookie。預設情況下,Cookie不包括在CORS請求之中。設為true
,即表示伺服器明確許可,Cookie可以包含在請求中,一起發給伺服器。這個值也只能設為true
,如果伺服器不要瀏覽器傳送Cookie,刪除該欄位即可。成功登陸的響應頭大概如下圖,然後後面的請求,請求頭裡面都會自帶這個cookie,無需管理。
到這裡差不多就摸索完了,如果覺得問題解決了,歡迎點贊,有什麼疑問也可以討論,歡迎交流。