一、問題
前后端分離項目,使用了session保存用戶的信息,用戶登錄成功后,用同一個token去獲取用戶信息時,出現了提示該用戶未登錄的錯誤。
二、原因
前端使用ajax請求,涉及到跨域問題,導致了同一個用戶的請求的session_id不一致,所以出現上述問題,日志捕獲到的session_id信息如下:
服務端設置的允許跨域訪問代碼如下【PHP】:
header('Access-Control-Allow-Origin: *'); // 允許所有來源訪問 header("Access-Control-Allow-Methods: *"); // 允許所有的請求方式 header('Access-Control-Allow-Headers: *'); // 允許攜帶任意的請求頭 header('Access-Control-Allow-Credentials: true'); // 允許客戶端攜帶驗證信息,例如 cookie 之類的
以上設置其實是存在沖突的。
CORS請求默認不發送Cookie和HTTP認證信息。如果要把Cookie發到服務器,一方面要服務器同意,指定Access-Control-Allow-Credentials
字段,另一方面,開發者必須在AJAX請求中打開withCredentials
屬性,需要注意的是,如果要發送Cookie,Access-Control-Allow-Origin
就不能設為星號,必須指定明確的、與請求網頁一致的域名
這里可以參考阮一峰老師的文章:跨域資源共享 CORS 詳解【尤其需要注意的是簡單請求和復雜請求的理解】
三、解決
服務端設置的允許跨域訪問代碼如下【PHP、TP3.2】:
//允許跨域 $origin = isset($_SERVER['HTTP_ORIGIN'])? $_SERVER['HTTP_ORIGIN'] : '"' . get_client_ip() . '"'; header('Access-Control-Allow-Origin:'.$origin); // 動態設置允許來源 header("Access-Control-Allow-Methods: *"); header('Access-Control-Allow-Headers: Content-Type,Accept-Charset'); // Content-Type:只限於三個值application/x-www-form-urlencoded
、multipart/form-data
、text/plain 才屬於簡單請求,時間項目中的值為:application/json
header('Access-Control-Allow-Credentials: true');
前端請求設置withCredentials屬性,比如【vue.js】:
axios.defaults.withCredentials = true;
問題解決,日志捕獲到的session_id信息如下:
四、參考鏈接
1、http://www.ruanyifeng.com/blog/2016/04/cors.html
2、https://segmentfault.com/a/1190000006095018