axios cookie问题和表单上传问题探究

原创 hongchh 随笔 开发记录 428阅读 2017-05-24 14:22:00 举报

自从入了Vue之后,一直在用axios这个库来做一些异步的ajax请求。最近在跨域、cookie 以及表单上传这几个方面遇到了点小问题,做个简单探究和总结。本文将涉及使用 axios 在跨域情况下成功得到响应报文中的内容以及让cookie成功设置的解决办法;使用axios上传表单数据时候遇到的小问题。

更好的排版请查看:http://blog.csdn.net/hongchh/article/details/72675777

一、同域 cookie 问题

首先来看一个同域情况下的cookie例子清楚整个流程以便后面对跨域情况能够更好地阐述。服务端的代码如下,访问/get-cookie接口的时候,通过session随便设置字段time,使得响应报文中带有set-cookie字段,在浏览器段设置cookie,这个cookie的内容即相应的sessionId。然后访问/test-cookie可以判断浏览器端的cookie是否设置成功,如果设置成功,那么浏览器发送的报文会自动带上cookie字段,服务器也就可以根据cookie找到对应的session。如果设置失败,那么浏览器发送的报文不会带上cookie字段,服务器也就无法找到对应的session,从而返回error。
javascript 代码

前端的代码如下,前端只有两个按钮,触发点击事件分别可以调用两个接口。
javascript 代码

首先点击 get-cookie 按钮,再点击 test-cookie 按钮,发送的报文信息如下,可以看到,get-cookie 的响应报文中有 set-cookie 字段,而 test-cookie 的请求报文中自动带上了 cookie 字段。通过 Chrome 的开发者工具也可以看到设置 cookie 成功。服务端也输出了响应的 session 和 cookie 的信息。

axioscookie问题和表单上传问题探究

axioscookie问题和表单上传问题探究

axioscookie问题和表单上传问题探究

axioscookie问题和表单上传问题探究

二、跨域 cookie 问题

为了实现跨域,将服务器拆分成 2 个服务器,1个提供静态资源,1个提供接口。访问8002端口的服务器加载前端的界面,然后跨域访问8001端口的服务器调用 get-cookie 和 test-cookie 接口。为了满足跨域,8001服务器的响应报文里面应该有 Access-Control-Allow-Origin 字段,字段值设置为 '*' 表示满足所有其他域的访问。
javascript 代码

javascript 代码

前端只需要小做修改,将调用接口的 URL 改为绝对地址。下面是 get-cookie 的写法,test-cookie 也类似。
javascript 代码

同样地,先 get-cookie,然后 test-cookie,得到的结果如下。访问没有出错,但是也没有成功设置 cookie。可以看到 get-cookie 的响应报文里面是有 set-cookie 字段的,但是 test-cookie 的请求报文并没有带上 cookie 字段。通过 Chrome 的开发者工具也可以看到 cookie 没有设置成功。

axioscookie问题和表单上传问题探究

axioscookie问题和表单上传问题探究

axioscookie问题和表单上传问题探究

查看 axios 的文档之后,发现需要配置 withCredentials 属性,在全局配置 axios 的 withCredentials 属性为 true。
javascript 代码

配置完成之后再进行测试,得到的结果如下。确实成功设置了 cookie,test-cookie 的请求报文会自动带上 cookie。但是前端除了成功设置 cookie 之外,还会报错,而且无法读取到响应报文的主体部分的内容。

axioscookie问题和表单上传问题探究

axioscookie问题和表单上传问题探究

axioscookie问题和表单上传问题探究

axioscookie问题和表单上传问题探究

根据错误提示,应该是说不能直接将 Access-Control-Allow-Origin 字段的值设置为 '*'。因此,我们直接将其值修改为确定的域名试试。对 get-cookie 和 test-cookie 作如下修改。
javascript 代码

继续进行测试,得到的结果跟之前相似,成功设置了 cookie,但却无法获取响应报文的主体部分的内容,并且继续报错了。其他内容相似这里不重复截图。只有这个报错的信息是不同的,如下图所示。看样子修改为确定的域名成功解决了之前那个问题,接下来需要解决这新的问题。

axioscookie问题和表单上传问题探究

根据报错提示,是说除了 Access-Control-Allow-Origin 字段之外,我们还需要设置 Access-Control-Allow-Credentials 的值为 true。根据提示对服务端代码进行修改,如下所示。
javascript 代码

继续进行测试,得到结果如下。这次除了可以正确设置 cookie 之外,也可以读取到响应报文的主体部分的内容,并且没有任何报错。

axioscookie问题和表单上传问题探究

axioscookie问题和表单上传问题探究

axioscookie问题和表单上传问题探究

因此,可以得到结论,在跨域的情况下使用 axios,首先需要配置 axios 的 withCredentials 属性为 true。然后服务器还需要配置响应报文头部的 Access-Control-Allow-Origin 和 Access-Control-Allow-Credentials 两个字段,Access-Control-Allow-Origin 字段的值需要为确定的域名,而不能直接用 '*' 代替,Access-Control-Allow-Credentials 的值需要设置为 true。前端和服务端两边都配置完善之后就可以正常进行跨域访问以及携带 cookie 信息了。

三、表单上传问题

之前在使用 axios 上传表单数据的过程中,我通常像下面会这么做。
javascript 代码

上面这种做法在 NodeJS express 服务端使用 body-parser 可以正确解析到请求报文里面 body 部分的数据,也就是我提交的表单数据,所以这样玩了很久也没有出现过什么问题。直到最近在课程作业中跟1个 Python flask 后台的同学协作过程中才开始踩到坑。用上面那种方式提交的数据,在他的后台程序里面提取不到表单数据。他的后台通过 req.form 的方式获取表单数据,跟 express 的 req.body 好像有那么一点不同。于是我猜想 express 的 body-parser 中间件是把报文的主体部分的数据都提取了出来,而他的 req.form 只会提取标准的表单数据。通过修改 axios post 的数据也可以验证猜想。代码修改如下,使用 js 提供的 FormData 来包装需要提交的表单数据。最后服务器也成功收到了前端上传的数据。
javascript 代码

这时候大概可以简单理解一下两者区别,第一种方式是 post 了一个 js 对象,会被变成 json 字符串的形式提交。而第二种则是提交了一个 FormData 对象,标准的表单数据对象。因此,如果在 Java、PHP 等其他后台遇到类似的问题时,也可以考虑尝试用 FormData 对象来解决。

评论 ( 0 )
最新评论
暂无评论

赶紧努力消灭 0 回复