ajax如何解决跨域问题
# 什么是跨域
我们所说的跨域,指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对 JavaScript
施加的安全限制。 在此说明一下,所谓的同源,指的是域名、协议、端口均相等。举例如下:
http://www.abc.com/a/b 调用 http://www.abc.com/d/c(非跨域)
http://www.abc.com/a/b 调用 http://www.def.com/d/c (跨域:域名不一致)
http://www.abc.com:81/a/b 调用 http://www.abc.com:82/d/c (跨域:端口不一致)
http://www.abc.com/a/b 调用 https://www.abc.com/d/c (跨域:协议不同)
2
3
4
另外值得注意的是,localhost
和 127.0.0.1
虽然都指向本机,但也属于跨域。在一个 http
请求中,http
头部 Referer
或 Origin
字段标识了当前域名,Host
字段标识了此时请求的域名。所以通过 ajax
请求第三方的数据,就会出现浏览器的跨域问题。
# 如何解决跨域
解决跨域问题,有如下三种方式:
# 1、使用jsonp
JSONP
是JSON with Padding
的略称。它是一个非官方的协议,它允许在服务器端集成Script tags
返回至客户端,通过javascript callback
的形式实现跨域访问(这仅仅是JSONP
简单的实现形式)。jsonp
解决跨域问题的原理是,浏览器的script
标签是不受同源策略限制的,我们可以在script
标签中访问任何域名下的资源文件。利用这一特性,用script
标签从服务器中请求数据,同时服务器返回一个带有方法和数据的js
代码,请求完成,调用本地的js
方法,来完成数据的处理。 更多关于jsonp
的使用方式,可以参考Jsonp和java操作例子 (opens new window),优缺点可以参考JSONP原理优缺点(只能GET不支持POST) (opens new window)。以
Jquery
的ajax
方法为例:$.ajax({ url:"", dataType:'jsonp', data:'', jsonp:'callback', //传递给请求处理程序或页面的 //用以获得jsonp回调函数名的参数名(默认为:callback) success:function(result) { //成功的处理 }, error:function(){ //错误处理 } });
1
2
3
4
5
6
7
8
9
10
11
12
13
14服务端此时返回的不能是普通的
json
字符串,而是一段可以被前端js
执行的一段js代码。json
与jsonp
格式的区别://json格式 { "message":"获取成功", "state":"1", "result":{"name":"工作组1","id":1,"description":"11"} }
1
2
3
4
5
6//jsonp格式 callback({ "message":"获取成功", "state":"1", "result":{"name":"工作组1","id":1,"description":"11"} })
1
2
3
4
5
6从格式来看,
jsonp
是在json
的基础上包装了一个方法名,此方法名是前端请求传过来的。注意
jsonp的缺点:
JSONP
是一种非官方的方法,而且这种方法只支持GET
方法,不如POST
方法安全。(从实现机制就可明白)。JSONP
的实现需要服务器配合,如果是访问的是第三方的服务器,我们没有修改服务器的权限,那么这种方式是不可行的。
# 2、服务器代理
如果服务器A的test01.html页面想访问服务器B的后台action,返回“test”字符串,此时就出现跨域请求,浏览器控制台会出现报错提示,由于跨域是浏览器的同源策略造成的,对于服务器后台不存在该问题,可以在服务器A中添加一个代理action,在该action中完成对服务器B中action数据的请求,然后在返回到test01.html页面。这种方式运用的就是服务器的反向代理技术,控制客户端和服务器的访问都从代理服务器经过,比如用nginx作为服务器代理,在nginx上配置客户端和第三方服务的反向代理,这样就可保证客户端、第三方是同源的了,同一个源,都来自代理服务器。关于 nginx
的反向代理配置,可访问:http://blog.csdn.net/csdn_ds/article/details/58605591
注意
服务器代理的缺点: 开发比较麻烦,对开发环境比较严格,需要在本机上配置代理服务器。
::: info 服务器代理的优点: 完美解决使用jsonp,第三方服务没有修改权限的问题。程序的代码侵入性小,代码级别不需要考虑跨域问题。 :::
# 3、添加响应头
可以在服务端设置 response header
中 Access-Control-Allow-Origin
字段
addHeader(‘Access-Control-Allow-Origin:*’);//允许所有来源访问
addHeader(‘Access-Control-Allow-Method:POST,GET’);//允许访问的方式
2
在被请求的 Response Header
中加入如下代码:
// 指定允许其他域名访问
response.setHeader("Access-Control-Allow-Origin", "*");
// 响应类型
response.setHeader("Access-Control-Allow-Methods", "POST");
// 响应头设置
response.setHeader("Access-Control-Allow-Headers","x-requested-with,content-type");
2
3
4
5
6
如果所有请求都想让其他域名的服务通过浏览器ajax请求到,可以通过 Filter
统一设置response header
。此处说明一下:只设置 Access-Control-Allow-Origin
属性也是可以的。Access-Control-Allow-Origin:*
表示允许任何域名跨域访问,如果需要指定某域名才允许跨域访问,只需把 Access-Control-Allow-Origin:*
改为 Access-Control-Allow-Origin:允许的域名
例如:
response.setHeader("Access-Control-Allow-Origin","http://www.client.com");
注意
缺点: 此种解决跨域方案,需要浏览器支持H5,因为这是HTML5解决跨域的方式,如果产品面向的是PC端,这种方式可能就不是一个好的解决方案,如果面向的是手机端,此方法不为一个简单、粗暴的好方式。 设置*,存在安全隐患。
# 总结
服务代理最好,没有破坏浏览器的安全策略,但这个对开发环境要高一点。设置 response header
的方式,根据具体情况分析,要考虑清楚产品面向的用户。对于 jsonp
这种方式,虽然没有破坏浏览器的安全策略,但只支持 get
方式的请求,有点不能接受,因为 get
传输有参数长度的限制,同时又要考虑传输中文的乱码问题,但如果项目中只是简单的查询、展示,这种方式还是可以考虑的。
- 01
- linux 在没有 sudo 权限下安装 Ollama 框架12-23
- 02
- Express 与 vue3 使用 sse 实现消息推送(长连接)12-20