本地web访问远程服务器后端引发的跨域问题

来源:互联网 发布:网站空间送域名 编辑:程序博客网 时间:2024/05/18 00:04

首先,说明一下案例性质,web调用restApi。

其次,说明一下案例的基本情况。我在本地编写的web程序,后端程序保存在远程服务器端,如166.66.66.6:8000/setup。


本次介绍的跨域的解决办法,不涉及jsonp方式。而是需要将后端的代码中设置Access-Control-Alow-Origin = “*”,表示允许一切跨域访问。Access-Control-Alow-Origin一次只能设置一个域名,但是如果想要同时设置多个域名的话,解决办法是,建立一个允许跨域请求的域名列表,然后获取请求来源域名,和列表进行对比,如果来源域名存在允许的跨域请求域名列表里面,再添加Access-Control-Alow-Origin响应头。

第 一次出现问题的情况: $.ajax中设置url:“……”,data:{ “name”, “xiaobai”;“age”,“22” },type:“post”,则会发生报错400,response提示{"ret":-1,"info":"Failed to parse JSON invalid character 'a' looking for beginning of value"},意思是传送的数据没能成功转为JSON字符串。这时,将设置改为data:JSON.stringify{ “name”, “xiaobai”;“age”,“22” },dataType:“json”则成功。。这里dataType是对返回的数据进行格式的转换。原理解释一下,

注意,这里出现的问题,如果web代码和后端代码在同一个域时,则会自动转为JSON格式。而不需要JSON.stringify转化。还有一点,若web代码在本地,后端代码在服务器端,可以通过nginx代理,使其避开跨域问题的发生。


第二次出现问题的情况:如果只是简单的post发送方式,将json格式的数据发送到后端,则按照上述第一次出现的情况,即可解决问题。当需要在ajax中加入

beforeSend:function(xhr){    xhr.setRequestHeader("Authorization", userToken);//xhr.setRequestHeader("Content-Type", "application/json");},
时,又会出现报错提示:
Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.
这 个时候,问题出现在content-type出现了问题。因为我们准备的数据时string格式的,同时ajax默认提交时告诉服务器数据格式是 "'application/x-www-form-urlencoded",当我们用JSON.stringify转化数据后,服务器调用相关的 Converter解析的时候发现解析不了(因为我们的数 据格式其实是json格式)。由于content-type的不正确,导致post方法,用options方式发送过去了。故而,由于发送方式不同,后端 不能正确接收数据。
解决办法是(后台的处理方式):
location / {           if ($request_method = OPTIONS ) {               add_header Access-Control-Allow-Origin  "*";               add_header Access-Control-Allow-Methods "POST, GET, PUT, UPDATE, DELETE, OPTIONS";               add_header Access-Control-Allow-Headers "Authorization";               add_header Access-Control-Allow-Credentials  "true";               add_header Content-Length 0;               add_header Content-Type text/plain;               return 200;           }location ~ ^/(join|login|logout|user)$ {            if ($request_method = OPTIONS) {                rewrite ^(.*)$ / last;            }} 

第三次出现问题的情况,如果用angularjs的$http发送数据,则又会提示跨域的错误提示,那么添加headers:{“content-type”:“application/x-www-form-urlencoded”};则请求成功。


综上,虽然问题已经解决了,而且基本确定是content-type变化导致的问题,可是我有几点疑问没有解决。

第一点,post变options是因为content-type的原因,可是我本地没有设置request的content-type,后端没有设置response的content-type,而是只在后端设置了if ($request_method = OPTIONS) {rewrite ^(.*)$ / last;},就能解决跨域问题。这是为什么?

第二点是,JSON.stringify使content-type默认值改变,导致问题发生,可以只在后台设置了Access-Control-Allow-Headers=“*”,而没有设置request的content-type就成功了,这又是为什么?

以上均为个人理解,有误之处,请指正。也希望有大神帮忙解决一下我的问题~~~

http://www.cnblogs.com/taoys/archive/2010/12/30/1922186.html 讲解content-type中application/x-www-form-urlencoded内容;

http://fyq891014.blog.163.com/blog/static/20074019120123305029795/ 讲解jquery,ajax参数的问题;

http://www.cnblogs.com/yeer/archive/2009/07/23/1529460.html 讲解jquery中ajax参数问题(更详细);


首先,说明一下案例性质,web调用restApi。

其次,说明一下案例的基本情况。我在本地编写的web程序,后端程序保存在远程服务器端,如166.66.66.6:8000/setup。


本次介绍的跨域的解决办法,不涉及jsonp方式。而是需要将后端的代码中设置Access-Control-Alow-Origin = “*”,表示允许一切跨域访问。Access-Control-Alow-Origin一次只能设置一个域名,但是如果想要同时设置多个域名的话,解决办法是,建立一个允许跨域请求的域名列表,然后获取请求来源域名,和列表进行对比,如果来源域名存在允许的跨域请求域名列表里面,再添加Access-Control-Alow-Origin响应头。

第 一次出现问题的情况: $.ajax中设置url:“……”,data:{ “name”, “xiaobai”;“age”,“22” },type:“post”,则会发生报错400,response提示{"ret":-1,"info":"Failed to parse JSON invalid character 'a' looking for beginning of value"},意思是传送的数据没能成功转为JSON字符串。这时,将设置改为data:JSON.stringify{ “name”, “xiaobai”;“age”,“22” },dataType:“json”则成功。。这里dataType是对返回的数据进行格式的转换。原理解释一下,

注意,这里出现的问题,如果web代码和后端代码在同一个域时,则会自动转为JSON格式。而不需要JSON.stringify转化。还有一点,若web代码在本地,后端代码在服务器端,可以通过nginx代理,使其避开跨域问题的发生。


第二次出现问题的情况:如果只是简单的post发送方式,将json格式的数据发送到后端,则按照上述第一次出现的情况,即可解决问题。当需要在ajax中加入

beforeSend:function(xhr){    xhr.setRequestHeader("Authorization", userToken);//xhr.setRequestHeader("Content-Type", "application/json");},
时,又会出现报错提示:
Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.
这 个时候,问题出现在content-type出现了问题。因为我们准备的数据时string格式的,同时ajax默认提交时告诉服务器数据格式是 "'application/x-www-form-urlencoded",当我们用JSON.stringify转化数据后,服务器调用相关的 Converter解析的时候发现解析不了(因为我们的数 据格式其实是json格式)。由于content-type的不正确,导致post方法,用options方式发送过去了。故而,由于发送方式不同,后端 不能正确接收数据。
解决办法是(后台的处理方式):
location / {           if ($request_method = OPTIONS ) {               add_header Access-Control-Allow-Origin  "*";               add_header Access-Control-Allow-Methods "POST, GET, PUT, UPDATE, DELETE, OPTIONS";               add_header Access-Control-Allow-Headers "Authorization";               add_header Access-Control-Allow-Credentials  "true";               add_header Content-Length 0;               add_header Content-Type text/plain;               return 200;           }location ~ ^/(join|login|logout|user)$ {            if ($request_method = OPTIONS) {                rewrite ^(.*)$ / last;            }} 

第三次出现问题的情况,如果用angularjs的$http发送数据,则又会提示跨域的错误提示,那么添加headers:{“content-type”:“application/x-www-form-urlencoded”};则请求成功。


综上,虽然问题已经解决了,而且基本确定是content-type变化导致的问题,可是我有几点疑问没有解决。

第一点,post变options是因为content-type的原因,可是我本地没有设置request的content-type,后端没有设置response的content-type,而是只在后端设置了if ($request_method = OPTIONS) {rewrite ^(.*)$ / last;},就能解决跨域问题。这是为什么?

第二点是,JSON.stringify使content-type默认值改变,导致问题发生,可以只在后台设置了Access-Control-Allow-Headers=“*”,而没有设置request的content-type就成功了,这又是为什么?

不确定,我写的这些是否正确,如果疑问,欢迎指正。也希望有大神帮忙解决一下我的问题~

http://www.cnblogs.com/taoys/archive/2010/12/30/1922186.html 讲解content-type中application/x-www-form-urlencoded内容;

http://fyq891014.blog.163.com/blog/static/20074019120123305029795/ 讲解jquery,ajax参数的问题;

http://www.cnblogs.com/yeer/archive/2009/07/23/1529460.html 讲解jquery中ajax参数问题(更详细);


0 0