一、问题
前后端分离项目,使用了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