JSONP ———— 跨域解决方案之一

1 篇文章 0 订阅

前言:在实际的开发应用过程中,很有可能需要获取另外一个服务器上的资源,如果两个服务器的域名、端口、协议等不同,就存在跨域问题。

 

一、什么是跨域?

简单的来讲就是浏览器不能执行其他网站的脚本,主要原因在于浏览器的同源策略。而同源策略又分成:

1.DOM同源策略

2.XMLHttpRequest同源策略

这里主要讲的是如何解决XMLHttpRequest同源策略。

比如有两个服务器,分别是A服务器(www.servicea.com)和B服务器(www.serviceb.com),A服务器向B服务器发起一个ajax请求,这时候就会产生跨域问题。

 

二、哪些情况存在跨域问题?

当端口、协议、域名(即使与域名对应的ip)等任意一个不同,就构成跨域。

链接说明同源检测

http://www.servicea.com/first.do

http://www.servicea.com:8080/first.do

端口不同跨域

http://www.servicea.com/first.do

https://www.servicea.com/first.do

协议不同跨域

http://www.servicea.com/first.do

http://www.serviceb.com/first.do

域名不同跨域

http://www.servicea.com/first.do

http://10.28.10.13/first.do

域名和其对应的ip跨域

http://www.servicea.com/first.do

http://img.servicea.com/first.do

子域不同跨域

http://www.servicea.com/first.do

http://www.servicea.com/second.do

同域名不同方法不跨域

http://www.servicea.com/first.do

http://www.servicea.com/web/first.do

同域名不同文件夹不跨域
   

三、什么是JSONP(JSON With Padding)?

动态添加<script>来调用服务器提供的js脚本。

这是一种非正式的传输方式,由于发现js文件不受同源策略的影响,包括含有src的标签都不受影响。所以通过web动态添加<script>,通过src调用服务器同时带上一个callback的参数,服务器创建一个包裹返回数据的函数,函数名就是callback的参数,最终返回一个可执行的js函数调用。

 

四、如何使用JSONP解决跨域问题?

现有如下两个服务器:A: http://localhost:8080 和B:http://localhost:8888,浏览器访问地址:

http://localhost:8080/mybatis/jsp/test.jsp

 

1、正常ajax访问,出现的跨域问题

访问 http://localhost:8080/mybatis/home

前端代码:

$.ajax({
	url : 'http://localhost:8080/mybatis/home',
	type : 'get',
	data : {
		name : "8080"
	},
	success : function(resp) {
		console.log(resp);
	}
});

服务器:

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String name = req.getParameter("name");
    resp.getWriter().append("welcome "+ name + " !");
}

结果:正常访问

 

访问http://localhost:8888/mybatis/home

前端代码:

$.ajax({
	url : 'http://localhost:8888/mybatis/home',
	type : 'get',
	data : {
		name : "8888"
	},
	success : function(resp) {
		console.log(resp);
	}
});

服务器:

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String name = req.getParameter("name");
    resp.getWriter().append("welcome "+ name + " !");
}

结果:不能访问

因为同源策略,端口不同出现跨域访问。

 

2、动态创建script

访问http://localhost:8888/mybatis/home

前端代码:

$("head").append("<script src='http://localhost:8888/mybatis/ScriptServlet?name=script&callback=testscript'><\/script>");

//或者如下js
//var sc = document.createElement("script");
//sc.src = "http://localhost:8888/mybatis/ScriptServlet?name=script&callback=testscript";
//document.body.insertBefore(sc,document.body.firstChild);


function testscript(resp) {
	console.log(resp);
}

服务器:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String callback = request.getParameter("callback");
    String name = request.getParameter("name");
    response.getWriter().append(callback+"(\""+name+"\")");
}

结果:可以访问

通过js创建一个<script>标签,同时在请求的地址中拼接一个callback=testscript的参数;

在服务器中,获取callback的参数值,与返回数据拼装成一个可执行的函数:testscript("+返回的数据+");

返回到web后自动执行testscript函数。

 

3、jquery的JSONP方式

访问http://localhost:8888/mybatis/home

前端代码:

$.ajax({
    url : 'http://localhost:8888/mybatis/ScriptServlet',
    type : 'get',
    data : {
	    name : 'test 8888,jsonp'
    },
    dataType : 'jsonp',
//      jsonp:'othercallback', //指定参数名称,即callback改为othercallback,所以后台获取相应也要改为request.getParameter("othercallback")
//      jsonpCallback:'othername', //指定回调函数名称
    success : function(resp) {
		console.log(resp);
    }
});

服务器:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String callback = request.getParameter("callback");
    String name = request.getParameter("name");
    response.getWriter().append(callback+"(\""+name+"\")");
}

结果:可以访问

只需要在ajax方法里,添加一个dataType:'jsonp'参数即可。乍一看,咋没有回调函数的名称,其实查看url就知道了,

 

4、jsonp全部参数

访问http://localhost:8888/mybatis/home

前端代码:

$.ajax({
    url : 'http://localhost:8888/mybatis/ScriptServlet',
    type : 'get',
    data : {
	    name : 'test 8888,jsonp'
    },
    dataType : 'jsonp',
    jsonp:'othercallback', //指定参数名称,即callback改为othercallback,所以后台获取相应也要改为request.getParameter("othercallback")
    jsonpCallback:'othername', //指定回调函数名称
    success : function(resp) {
		console.log("ajax:"+resp);
    }
});


function othername(resp){
    console.log("othername:"+resp);
}

服务器:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String callback = request.getParameter("othercallback");
    String name = request.getParameter("name");
    response.getWriter().append(callback+"(\""+name+"\")");
}

结果:可以访问

返回web后先执行了othername函数,最后执行success。

 

5、使用getJSON

访问http://localhost:8888/mybatis/home

前端代码:

$.getJSON("http://localhost:8888/mybatis/ScriptServlet?name=getJSON&othercallback=?",function(resp){
	console.log(resp);
});

服务器:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String callback = request.getParameter("othercallback");
    String name = request.getParameter("name");
    response.getWriter().append(callback+"(\""+name+"\")");
}

结果:可以访问

6、前端全部代码

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>This is 8080 page</title>
</head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js">
	
</script>
<script type="text/javascript">
	$(function() {
		$("a").click(function() {
			switch ($(this).attr("id")) {
			case "1":
				$.ajax({
					url : 'http://localhost:8080/mybatis/home',
					type : 'get',
					data : {
						name : "8080"
					},
					success : function(resp) {
						console.log(resp);
					}
				});
				break;
			case "2":
				$.ajax({
					url : 'http://localhost:8888/mybatis/home',
					type : 'get',
					data : {
						name : "8888"
					},
					success : function(resp) {
						console.log(resp);
					}
				});
				break;
			case "3":
				$("head").append("<script src='http://localhost:8888/mybatis/ScriptServlet?name=script&callback=testscript'><\/script>");
// 				var sc = document.createElement("script");
// 				sc.src = "http://localhost:8888/mybatis/ScriptServlet?name=script&callback=testscript";
// 				document.body.insertBefore(sc,document.body.firstChild);
				break;
			case "4":
				$.ajax({
				    url : 'http://localhost:8888/mybatis/ScriptServlet',
				    type : 'get',
				    data : {
					    name : 'test 8888,jsonp'
				    },
				    dataType : 'jsonp',
//				    jsonp:'othercallback', //指定参数名称,即callback改为othercallback,所以后台获取相应也要改为request.getParameter("othercallback")
//				    jsonpCallback:'othername', //指定回调函数名称
				    success : function(resp) {
						console.log(resp);
				    }
				});
				break;
			case "5":
				$.ajax({
				    url : 'http://localhost:8888/mybatis/ScriptServlet',
				    type : 'get',
				    data : {
					    name : 'test 8888,jsonp'
				    },
				    dataType : 'jsonp',
				    jsonp:'othercallback', //指定参数名称,即callback改为othercallback,所以后台获取相应也要改为request.getParameter("othercallback")
				    jsonpCallback:'othername', //指定回调函数名称
				    success : function(resp) {
						console.log("ajax:"+resp);
				    }
				});
				break;
            case "6":
				$.getJSON("http://localhost:8888/mybatis/ScriptServlet?name=getJSON&othercallback=?",function(resp){
					console.log(resp);
				});
			default:
				break;
			}
		});
	});
	
	function othername(resp){
	    console.log("othername:"+resp);
	}

	function testscript(resp) {
		console.log(resp);
	}
</script>
<body>
	<a href="javascript:void(0)" id="1">访问本homeservlet</a>
	<br />
	<a href="javascript:void(0)" id="2">访问8888 homeservlet</a>
	<br />
	<br />

	<a href="javascript:void(0)" id="3">动态创建script</a>
	<br>
	<a href="javascript:void(0)" id="4">jquery跨域请求</a>
	<br>
	<a href="javascript:void(0)" id="5">jquery跨域请求(自定义callback)</a>
	<br>
    <a href="javascript:void(0)" id="6">getJSON</a>
	<br>
</body>
</html>

 

五、JSONP主要弊端,缺陷

1、不支持post方式,即使在ajax中改成post,实际也是get方法

将以上ajax中的get改成post:

$.ajax({
    url : 'http://localhost:8888/mybatis/ScriptServlet',
    type : 'post',
    data : {
	    name : 'test 8888,jsonp'
    },
    dataType : 'jsonp',
//      jsonp:'othercallback', //指定参数名称,即callback改为othercallback,所以后台获取相应也要改为request.getParameter("othercallback")
//      jsonpCallback:'othername', //指定回调函数名称
    success : function(resp) {
		console.log(resp);
    }
});

看起来请求成功了,但是实际最终还是get请求,

 

  因为jsonp是通过动态创建script,而动态生成script的src只能用get。

2、JSONP是一种脚本注入,存在一定的安全隐患。

  安全问题可以参考:https://blog.csdn.net/u014021893/article/details/72303110

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值