AJAX跨域介绍

  AJAX 跨域访问是用户访问A网站时所产生的对B网站的跨域访问请求均提交到A网站的指定页面

  由于安全方面的原因, 客户端js使用xmlhttprequest只能用来向来源网站发送请求,比如在www.readlog.cn下去请求test.readlog.cn的数据,都是不行的。

  什么是AJAX跨域问题

  • 简单来说,就是前端调用后端服务接口时
  • 如果服务接口不是同一个域,就会产生跨域问题

  AJAX跨域场景

  • 前后端分离、服务化的开发模式
  • 前后端开发独立,前端需要大量调用后端接口的场景
  • 只要后端接口不是同一个域,就会产生跨域问题
  • 跨域问题很普遍,解决跨域问题也很重要

  AJAX跨域原因

  • 浏览器限制:浏览器安全校验限制
  • 跨域(协议、域名、端口任何一个不一样都会认为是跨域)
  • XHR(XMLHttpRequest)请求

  AJAX跨域问题解决思路

  • 浏览器:浏览器取下跨域校验,实际价值不大
  • XHR:不使用XHR,使用JSONP,有很多弊端,无法满足现在的开发要求
  • 跨域:被调用方修改支持跨域调用(指定参数);调用方修改隐藏跨域(基于代理)

  如图:

    

解决跨域问题

  实例

    1、新建一个SpringMVC的Maven工程,参考:【Maven】Eclipse 使用Maven创建SpringMVC Web项目,pom.xml文件如下:

 <project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.test</groupId>
<artifactId>test-ajax-cross</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<!-- 定义maven变量 -->
<properties>
<!-- spring -->
<spring.version>4.2.0.RELEASE</spring.version> <!-- log -->
<commons-logging.version>1.1.3</commons-logging.version> <!-- Servlet -->
<servlet.version>3.0.1</servlet.version>
<jsp-api.version>2.2</jsp-api.version> <!-- jstl -->
<jstl.version>1.2</jstl.version>
<standard.version>1.1.2</standard.version> <!-- Tool -->
<!-- jackson json包 -->
<jackson-databind.version>2.9.7</jackson-databind.version>
<jackson-core.version>2.9.7</jackson-core.version>
<jackson-annotations.version>2.9.7</jackson-annotations.version> <!-- test -->
<junit.version>3.8.1</junit.version> <!-- jdk -->
<jdk.version>1.8</jdk.version>
<maven.compiler.plugin.version>2.3.2</maven.compiler.plugin.version>
</properties> <dependencies> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency> <!-- Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servlet.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>${jsp-api.version}</version>
<scope>provided</scope>
</dependency> <!-- jstl -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency> <dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>${standard.version}</version>
</dependency> <!-- jackson json包 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson-databind.version}</version>
</dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson-core.version}</version>
</dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson-annotations.version}</version>
</dependency> <!-- test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency> </dependencies> <build>
<plugins>
<!-- define the project compile level -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.plugin.version}</version>
<configuration>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
</configuration>
</plugin>
</plugins>
<finalName>test-ajax-cross</finalName>
</build> </project>

    

    2、新建一个测试controller,注意返回的是一个json对象,项目中需要加入json依赖

 package com.test.ajax.cross.controller;

 import java.util.HashMap;
import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView; @Controller
@RequestMapping("/test")
public class TestController { @RequestMapping(value="/get")
@ResponseBody
public Map getTest(HttpServletRequest request){
Map<String, Object> map = new HashMap();
map.put("data", "TestController getTest()");
return map;
}
}

    3、新建一个测试界面webapp/static/test.html

 <!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="jquery-1.11.3.min.js" type="text/javascript"></script>
</head>
<body>
<h2>测试界面</h2>
<a href="#" onclick="get()">发送get请求</a>
</body>
<script type="text/javascript">
function get(){
$.getJSON("http://localhost:8080/test-ajax-cross/test/get").then(function(result){
console.log(result);
$("body").append("<br>" + JSON.stringify(result));
});
}
</script>
</html>

    4、将项目发布到Tomcat中,并访问测试界面,http://localhost:8080/test-ajax-cross/static/test.html

      

    5、修改hosts文件(用来映射域名与IP),将a.com映射到127.0.0.1,在使用地址:http://a.com:8080/test-ajax-cross/static/test.html#,访问,可以看到无法完成ajax请求了

      

  解决方案一(禁止浏览器检查)

    禁止浏览器检查,启动浏览器时,添加参数禁止浏览器对ajax做检查

    windows采用以下方式打开谷歌浏览器

"C:\Users\UserName\AppData\Local\Google\Chrome\Application\chrome.exe" --disable-web-security --user-data-dir
//不知道chrome.exe 地址的话
右键chrome图标-->属性-->如下图-->图中 目标 就是文件的位置了,直接复制出来即可

    mac采用以下方式打开谷歌浏览器

//chrome 浏览器
open -a "Google Chrome" --args --disable-web-security --user-data-dir
//safari 浏览器
open -a '/Applications/Safari.app' --args --disable-web-security --user-data-dir

    输入地址:http://localhost:8080/test-ajax-cross/static/test.html#,进行访问,可以看到能正常完成ajax请求了

      

  解决方案二(使用JSONP)

    Jsonp(JSON with Padding) 是 json 的一种"使用模式",可以让网页从别的域名(网站)那获取资料,即跨域读取数据。

    JSONP的基本思想是,网页通过添加一个<script>元素,向服务器请求JSON数据,这种做法不受同源政策限制;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来

  当通过<script>元素调用数据时,响应内容必须用javascript函数名和圆括号包裹起来。而不是发送这样一段JSON数据,这就是JSONP中P的意义所在

    在实践中,支持JSONP的服务不会强制指定客户端必须实现的回调函数名称,比如handleResponse。相反,它们使用査询参数的值,允许客户端指定一个函数名,然后使用函数名去填充响应。许多支持JSONP的服务都能分辨出这个参数名。另一个常见的参数名称是callback,为了让使用到的服务支持类似特殊的需求,就需要在代码上做一些修改了

    JSONP由两部分组成:回调函数和数据。回调函数是当响应到来时应该在页面中调用的函数。回调函数的名字一般是在请求中指定的。而数据就是传入回调函数中的JSON数据

    1、修改Java后台TestController类,增加jsonp的响应返回

 package com.test.ajax.cross.controller;

 import java.util.HashMap;
import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; @Controller
@RequestMapping("/test")
public class TestController { private ObjectMapper objectMapper = new ObjectMapper(); @RequestMapping(value="/get")
@ResponseBody
public Map getTest(HttpServletRequest request){
Map<String, Object> map = new HashMap();
map.put("data", "TestController getTest()");
return map;
} @RequestMapping(value="/getJsonp")
@ResponseBody
public String getJsonp(HttpServletRequest request) throws JsonProcessingException{
// 与前端约定好回调方法名称,默认是callback
String callback = request.getParameter("callback");
Map<String, Object> map = new HashMap();
map.put("data", "TestController getTest()");
String ret = callback+"("+ objectMapper.writeValueAsString(map)+")";
return ret;
}
}

    2、新建一个测试界面webapp/static/test2.html,用于jsonp请求,

 <!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="jquery-1.11.3.min.js" type="text/javascript"></script>
</head>
<body>
<h2>测试jsonp界面</h2>
<a href="#" onclick="get()">发送get请求</a>
</body>
<script type="text/javascript">
function get(){ $.ajax({
url: "http://localhost:8080/test-ajax-cross/test/getJsonp",
dataType: "jsonp",
jsonp:"callback", // 默认值是callback,可以修改
success: function (result) {
console.log(result);
$("body").append("<br>" + JSON.stringify(result));
}
});
}
</script>
</html>

    3、浏览器中输入地址:http://a.com:8080/test-ajax-cross/static/test2.html#,进行访问

      观察:使用F12查看请求

      参数callback对应的值是,请求响应后的回调方法

      参数_作用,值是随机数,为了是请求不使用缓存

      返回内容是:jQuery111306019926935268467_1567783875359({"data":"TestController getTest()"})

      

        

      注意:JSONP的弊端

      • 服务器需要改动代码支持
      • 只支持GET
      • 发送的不是XHR请求

      

【JS】AJAX跨域-JSONP解决方案(一)的更多相关文章

  1. JS Ajax跨域访问

    js ajax跨域访问报"No 'Access-Control-Allow-Origin' header is present on the requested resource 如果请求的 ...

  2. Ajax进阶之原生js与跨域jsonp

    什么是Ajax? 两个数求和: 用Jquery和数据用json格式 viws函数: from django.shortcuts import render,HttpResponse # Create ...

  3. ajax跨域请求解决方案

    大家好,今天我们学习了js的跨域请求的解决方案,由于JS中存在同源策略,当请求不同协议名,不同端口号.不同主机名下面的文件时,将会违背同源策略,无法请求成功!需要进行跨域处理! 方案一.后台PHP进行 ...

  4. java、ajax 跨域请求解决方案('Access-Control-Allow-Origin' header is present on the requested resource. Origin '请求源' is therefore not allowed access.)

      1.情景展示 ajax调取java服务器请求报错 报错信息如下: 'Access-Control-Allow-Origin' header is present on the requested ...

  5. jQuery的ajax跨域 Jsonp原理

    1.Jsonp Jsonp(json with padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题. Jsonp是为了解决ajax跨域发送http请求出现的,利用S ...

  6. ajax跨域问题解决方案

    今天来记录一下关于ajax跨域的一些问题.以备不时之需. 跨域 同源策略限制 同源策略阻止从一个域上加载的脚本获取或操作另一个域上的文档属性.也就是说,受到请求的 URL 的域必须与当前 Web 页面 ...

  7. AJAX 跨域 CORS 解决方案

    本篇文章由:http://xinpure.com/solutions-for-cross-domain-ajax-cors/ 两种跨域方法 在 Javascript 中跨域访问是比较常见的事情 就像现 ...

  8. ajax跨域问题解决方案(jsonp,cors)

    跨域 跨域有三个条件,满足任何一个条件就是跨域 1:服务器端口不一致 2:协议不一致 3:域名不一致 解决方案: 1.jsonp 在远程服务器上设法动态的把数据装进js格式的文本代码段中,供客户端调用 ...

  9. PHP下ajax跨域的解决方案之jsonp

    首先要说明一下json和jsonp的区别? json是一种基于文本的数据交换方式,或者叫做描述数据的一种格式. var person = { "name": "test& ...

随机推荐

  1. Python并发编程-GIL全局解释器锁

    Python并发编程-GIL全局解释器锁 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.GIL全局解释器锁概述 CPython 在解释器进程级别有一把锁,叫做GIL,即全局解释 ...

  2. 发布WS接口与实现WS接口[小列子]

    webservice简介:Web Service技术, 能使得运行在不同机器上的不同应用无须借助附加的.专门的第三方软件或硬件, 就可相互交换数据或集成.依据Web Service规范实施的应用之间, ...

  3. thinkphp5.x命令执行漏洞复现及环境搭建

    楼主Linux环境是Centos7,LAMP怎么搭不用我废话吧,别看错了 一.thinkphp5.X系列 1.安装composer yum -y install composer 安装php拓展 yu ...

  4. 移动端初始化常用JavaScript代码

    移动端常用js分享 1.把手机屏幕等分10分(我用的是这种形式),用rem来计算那些需要自适应. <script type="text/javascript"> (fu ...

  5. mysql终止当前正在执行的sql语句

    show processlist;找出你要停止的语句然后找出你要终止的语句的idkill 248

  6. ThreadLocal源码原理以及防止内存泄露

    ThreadLocal的原理图: 在线程任务Runnable中,使用一个及其以上ThreadLocal对象保存多个线程的一个及其以上私有值,即一个ThreadLocal对象可以保存多个线程一个私有值. ...

  7. shell脚本中向hive动态分区插入数据

    在hive上建表与普通分区表创建方法一样: CREATE TABLE `dwa_m_user_association_circle`( `device_number` string, `oppo_nu ...

  8. 如何使用powerdesigner导出sql脚本

    使用power designer可以很方便的对数据库设计进行管理,并且能够更方便的查看表与表之间的关系.同时,还可以对设计好的数据库直接导出创建脚本,根据不同的数据库实例导出对应的创建脚本,然后根据脚 ...

  9. HTML页面 js返回上一页

    <input type="button" name="Submit" onclick="javascript:history.back(-1); ...

  10. js中回调函数,promise 以及 async/await 的对比用法 对比!!!

    在编程项目中,我们常需要用到回调的做法来实现部分功能,那么在js中我们有哪些方法来实现回调的? 方法1:回调函数 首先要定义这个函数,然后才能利用回调函数来调用! login: function (f ...