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. Android Binder机制彻底梳理一

    Binder架构图: 先来瞅一下它的整体架构图: 其中粉红部分是上层的Binder,而蓝色的则是下层的Binder,很显然上层的是依赖于下层的. 什么是Binder[有个大概了解]? 这里从几个层面来 ...

  2. 微信小程序~Flex布局

    有一点需要注意的是,你的小程序要求兼容到iOS8以下版本,需要开启样式自动补全.开启样式自动补全,在“设置”—“项目设置”—勾选“上传代码时样式自动补全”.

  3. Incorrect integer value: '' for column 'id' at row 1 错误解决办法

    最近一个项目,在本地php环境里一切正常,ftp上传到虚拟空间后,当执行更新操作(我的目的是为了设置id为空)set id=‘’时提示: Incorrect integer value: '' for ...

  4. Linux——CentOS7没有第二张网卡的配置信息

    前言 为了一个实验做测试,在VMware中配置了环境,但是配置了双网卡后发现第二张网卡没有配置文件. 都是些基本命令就不写了,图里也有. 系统 : CentOS7.6 步骤 查看网卡信息 使用ip a ...

  5. nginx1.15.10配置使用非https访问返回403

    nginx版本号:nginx version: nginx/1.15.10 server { listen 443 default ssl; server_name app.test.com; if ...

  6. Django REST framework版本控制

    参考链接:https://www.cnblogs.com/liwenzhou/p/10269268.html 1.路由: #版本控制 re_path('^(?P<version>[v1|v ...

  7. 【洛谷P4093】 [HEOI2016/TJOI2016]序列 CDQ分治+动态规划

    你发现只会改变一个位置,所以可以直接进行dp 具体转移的话用 CDQ 分治转移就好了~ #include <bits/stdc++.h> #define N 100006 #define ...

  8. jedis的连接池

    1.需要先打开虚拟机,并开启Linux系统的端口号:6379: 其中,第一行代码为修改字符编码格式,解决SSH中文乱码问题. 2.开启redis: 3.利用连接池实现数据的存取: (1)代码实现: i ...

  9. nginx配置ssl加密(单/双向认证、部分https)

    nginx下配置ssl本来是很简单的,无论是去认证中心买SSL安全证书还是自签署证书,但最近公司OA的一个需求,得以有个机会实际折腾一番.一开始采用的是全站加密,所有访问http:80的请求强制转换( ...

  10. javascript使用history api防止|阻止页面后退

    奇葩需求啥时候都会有,最近有个需求是不允许浏览器回退,但是所有页面都是超链接跳转,于是乎脑壳没转弯就回答了做不到,结果尼玛被打脸了,这打脸的声音太响,终于静下心来看了下history api. 先上代 ...