什么是跨域问题?
跨域问题来源于JavaScript的"同源策略",即只有 协议+主机名+端口号 (如存在)相同,则允许相互访问。也就是说JavaScript只能访问和操作自己域下的资源,不能访问和操作其他域下的资源。跨域问题是针对JS和ajax的,html本身没有跨域问题。

查看浏览器开发者工具Console报错:

Failed to load http://a.a.com:8080/A/FromServlet?userName=123: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://b.b.com:8080’ is therefore not allowed access.

http://www.abc.com/a/b 调用 http://www.abc.com/d/c(非跨域)

http://www.abc.com/a/b 调用 http://www.def.com/a/b (跨域:域名不一致)

http://www.abc.com:8080/a/b 调用 http://www.abc.com:8081/d/c (跨域:端口不一致)

http://www.abc.com/a/b 调用 https://www.abc.com/d/c (跨域:协议不同)

请注意:localhost和127.0.0.1虽然都指向本机,但也属于跨域。

跨域问题怎么解决?
1、响应头添加Header允许访问

2、jsonp 只支持get请求不支持post请求

3、httpClient内部转发

4、使用接口网关——nginx、springcloud zuul (互联网公司常规解决方案)

解决方式1:响应头添加Header允许访问
跨域资源共享(CORS)Cross-Origin Resource Sharing

这个跨域访问的解决方案的安全基础是基于"JavaScript无法控制该HTTP头"

它需要通过目标域返回的HTTP头来授权是否允许跨域访问。

response.addHeader(‘Access-Control-Allow-Origin:*’);//允许所有来源访问
response.addHeader(‘Access-Control-Allow-Method:POST,GET’);//允许访问的方式

解决方式2:jsonp 只支持get请求不支持post请求
用法:①dataType改为jsonp ②jsonp : “jsonpCallback”————发送到后端实际为http://a.a.com/a/FromServlet?userName=644064&jsonpCallback=jQueryxxx ③后端获取get请求中的jsonpCallback ④构造回调结构

$.ajax({
type : “GET”,
async : false,
url : “http://a.a.com/a/FromServlet?userName=644064”,
dataType : “jsonp”,//数据类型为jsonp
jsonp : “jsonpCallback”,//服务端用于接收callback调用的function名的参数
success : function(data) {
alert(data[“userName”]);
},
error : function() {
alert(‘fail’);
}
});

//后端
String jsonpCallback = request.getParameter(“jsonpCallback”);
//构造回调函数格式jsonpCallback(数据)
resp.getWriter().println(jsonpCallback+"("+jsonObject.toJSONString()+")");
JSONP实现原理
在同源策略下,在某个服务器下的页面是无法获取到该服务器以外的数据的,即一般的ajax是不能进行跨域请求的。但 img、iframe 、script等标签是个例外,这些标签可以通过src属性请求到其他服务器上的数据。利用

当我们正常地请求一个JSON数据的时候,服务端返回的是一串JSON类型的数据,而我们使用 JSONP模式来请求数据的时候服务端返回的是一段可执行的JavaScript代码。因为jsonp 跨域的原理就是用的动态加载

示例:

$.ajax({

url: 'http://192.168.10.46/demo/test.jsp',        //不同的域type: 'GET',                                                        // jsonp模式只有GET 是合法的data: {'action': 'aaron'},dataType: 'jsonp',                                              // 数据类型jsonp: 'jsonpCallback',                                     // 指定回调函数名,与服务器端接收的一致,并回传回来

})

其实jquery 内部会转化成

http://192.168.10.46/demo/test.jsp?jsonpCallback=jQuery202003573935762227615_1402643146875&action=aaron

然后动态加载

然后后端就会执行jsonpCallback(传递参数 ),把数据通过实参的形式发送出去。

使用JSONP 模式来请求数据的整个流程:客户端发送一个请求,规定一个可执行的函数名(这里就是 jQuery做了封装的处理,自动帮你生成回调函数并把数据取出来供success属性方法来调用,而不是传递的一个回调句柄),服务器端接受了这个 jsonpCallback函数名,然后把数据通过实参的形式发送出去

(在jquery 源码中, jsonp的实现方式是动态添加

解决方式3:httpClient内部转发
实现原理很简单,若想在B站点中通过Ajax访问A站点获取结果,固然有ajax跨域问题,但在B站点中访问B站点获取结果,不存在跨域问题,这种方式实际上是在B站点中ajax请求访问B站点的HttpClient,再通过HttpClient转发请求获取A站点的数据结果。但这种方式产生了两次请求,效率低,但内部请求,抓包工具无法分析,安全。

$.ajax({
type : “GET”,
async : false,
url : “http://b.b.com:8080/B/FromAjaxservlet?userName=644064”,
dataType : “json”,
success : function(data) {
alert(data[“userName”]);
},
error : function() {
alert(‘fail’);
}
});

@WebServlet("/FromAjaxservlet")
public class FromAjaxservlet extends HttpServlet{

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {try {//创建默认连接CloseableHttpClient httpClient = HttpClients.createDefault();//创建HttpGet对象,处理get请求,转发到A站点HttpGet httpGet = new HttpGet("http://a.a.com:8080/A/FromServlet?userName="+req.getParameter("userName")); //执行CloseableHttpResponse response = httpClient.execute(httpGet);int code = response.getStatusLine().getStatusCode();//获取状态System.out.println("http请求结果为:"+code);if(code == 200){//获取A站点返回的结果String result = EntityUtils.toString(response.getEntity());System.out.println(result);//把结果返回给B站点resp.getWriter().print(result);}response.close();httpClient.close();} catch (Exception e) {}
}

}

解决方式4:使用nginx搭建企业级接口网关方式
www.a.a.com不能直接请求www.b.b.com的内容,可以通过nginx,根据同域名,但项目名不同进行区分。什么意思呢?这么说可能有点抽象。假设我们公司域名叫www.nginxtest.com

当我们需要访问www.a.a.com通过www.nginxtest.com/A访问,并通过nginx转发到www.a.a.com

当我们需要访问www.b.b.com通过www.nginxtest.com/B访问,并通过nginx转发到www.a.a.com

我们访问公司的域名时,是"同源"的,只是项目名不同,此时项目名的作用只是为了区分,方便转发。如果你还不理解的话,先看看我是怎么进行配置的:

server {
listen 80;
server_name www.nginxtest.com;
location /A {
proxy_pass http://a.a.com:81;
index index.html index.htm;
}
location /B {
proxy_pass http://b.b.com:81;
index index.html index.htm;
}
}
我们访问以www.nginxtest.com开头且端口为80的网址,nginx将会进行拦截匹配,若项目名为A,则分发到a.a.com:81。实际上就是通过"同源"的域名,不同的项目名进行区分,通过nginx拦截匹配,转发到对应的网址。整个过程,两次请求,第一次请求nginx服务器,第二次nginx服务器通过拦截匹配分发到对应的网址。

解决方式5:使用Spring Cloud zuul接口网关
我比较懒…

解决ajax跨域问题的5种解决方案相关推荐

  1. 解决ajax跨域问题【5种解决方案】

    什么是跨域问题? 跨域问题来源于JavaScript的"同源策略",即只有 协议+主机名+端口号 (如存在)相同,则允许相互访问.也就是说JavaScript只能访问和操作自己域下 ...

  2. 如何解决ajax跨域问题(转)

    由 于此前很少写前端的代码(哈哈,不合格的程序员啊),最近项目中用到json作为系统间交互的手段,自然就伴随着众多ajax请求,随之而来的就是要解决 ajax的跨域问题.本篇将讲述一个小白从遇到跨域不 ...

  3. 如何解决ajax跨域问题

    原文:http://www.congmo.net/blog/2012/06/27/ajax-cross-domain/ 跨域问题 起 因是这样的,为了复用,减少重复开发,单独开发了一个用户权限管理系统 ...

  4. 看小白如何解决ajax跨域问题

    由于此前很少写前端的代码(哈哈,不合格的程序员啊),最近项目中用到json作为系统间交互的手段,自然就伴随着众多ajax请求,随之而来的就是要解决ajax的跨域问题.本篇将讲述一个小白从遇到跨域不知道 ...

  5. Ajax跨域问题的两种解决方法

    Ajax跨域问题的两种解决方法 参考文章: (1)Ajax跨域问题的两种解决方法 (2)https://www.cnblogs.com/pandang/p/5341250.html 备忘一下.

  6. php json -gt;访问,【转】Php+ajax+jsonp解决ajax跨域问题

    首先:jsonp是json用来跨域的一个东西. 原理是通过script标签的跨域特性来绕过同源策略. 发送端: $.ajax({ type : "post", url : &quo ...

  7. [jQuery基础] jQuery案例 -- qq音乐以及初步解决Ajax 跨域问题

    qq音乐案例 案例效果展示 案例效果结构划分 整体布局 歌曲条目部分 顶部栏 底部栏 歌词显示部分 案例实现功能 a. QQ音乐播放器静态页面布局 * 页面整体布局规划和实现 * 页面顶部布局和静态效 ...

  8. 【Vue】Vue全家桶(三)Vue组件通信+Vue组件插槽+动画与过渡+使用vue-cli解决Ajax跨域问题

    1 Vue组件通信 1.1 组件间通信基本原则 不要在子组件中直接修改父组件的状态数据 数据在哪, 更新数据的行为(函数)就应该定义在哪 1.2 vue 组件间通信方式 props vue 的自定义事 ...

  9. Vue学习笔记05 组件的自定义事件-组件通信-$nextTick-脚手架解决ajax跨域-插槽-过渡动画

    文章目录 Vue学习笔记05 父组件给子组件传值 注意点 子组件给父组件传值 父组件接受子组件的传值 通过函数 组件的自定义事件 事件绑定的第一种写法 @或v-on 事件绑定的第二种写法:使用ref ...

最新文章

  1. Java项目:宿舍管理系统(java+jsp+SSM+Spring+mysql)
  2. 敏捷软件开发实践——估算与计划02
  3. GROMACS运行参数整理(二)
  4. 往事并不如烟@武汉 --- 和同事们一起'诈金花’
  5. randaugment
  6. javaweb之Java基础加强
  7. 使用canvas绘制小程序码
  8. 美国夫妇用数学算法买彩票赢1.74亿元——网友:现在学数学还来得及吗?
  9. linux中iconv函数,Linux下编码转换(iconv函数族)
  10. maven添加本地包命令mvn install:install-file
  11. 绕过AppLocker系列之MSBuild的利用
  12. SAP License:进项税的合理管理缩减成本
  13. 如何卸载 Internet Explorer 7
  14. Android应用程序组件Content Provider的启动过程源代码分析(5)
  15. 单片机原理及应用课程设计
  16. 如何使用scrapy中的ItemLoader提取数据?
  17. 64位:浪来滔滔江水永不休
  18. JS中的事件委托 / 代理详解
  19. 纹理基础知识和过滤模式详解
  20. java 线程执行结束_java中怎么判断线程执行完毕

热门文章

  1. [湖南大学程序设计实训训练作业二]5.点球大战
  2. table传统布局及实例
  3. 【前端静态页面HTML】
  4. 如何更新 Symantec AntiVirus 企业版的病毒定义
  5. 使用libqrencode库制作二维码电子名片--IOS版
  6. 一个 15 年 SAP ABAP 开发人员分享的 SAPGUI 一些个性化设置和实用小技巧试读版
  7. Java开发人员必须掌握的Linux命令-学以致用(五)
  8. Mac电脑上给google浏览器安装json解析插件
  9. 怎样解除电脑开机密码
  10. JMS及其API介绍