什么是 JsonP
Jsonp(JSON with Padding) 是 json 的一种"使用模式",可以让网页从别的域名(网站)那获取资料,即跨域读取数据。
为什么我们从不同的域(网站)访问数据需要一个特殊的技术(JSONP )呢?这是因为同源策略。
什么是跨域?
跨域是指一个域(网站)下的文档或脚本试图去请求另一个域(网站)下的资源。
什么是同源策略?
同源策略/SOP(Same origin policy)是一种约定,由 Netscape 公司 1995 年引入浏览器,它是浏览器最核心也最基本的安全功能,现在所有支持 JavaScript 的浏览器都会使用这个策略。如果缺少了同源策略,浏览器很容易受到 XSS、CSFR 等攻击。所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个 ip 地址,也非同源。
非同源策略限制以下几种行为:
1.) Cookie、LocalStorage 和 IndexDB 无法读取
2.) DOM 和 Js 对象无法获得
3.) AJAX 请求不能发送
常见跨域场景
跨域解决方案
1) 通过 jsonp 跨域
2) document.domain + iframe 跨域
3) location.hash + iframe
4) window.name + iframe 跨域
5) postMessage 跨域
6) 跨域资源共享(CORS)
7) nginx 代理跨域
8) nodejs 中间件代理跨域
9) WebSocket 协议跨域
JsonP 优缺点
JSONP 的优点是:它不像 XMLHttpRequest 对象实现的 Ajax 请求那样受到同源策略的限制;它的兼容性更好,在更加古老的浏览器中都 可以运行,不需要 XMLHttpRequest 或 ActiveX 的支持;并且在请求完毕后可以通过调用 callback 的方式回传结果。
JSONP 的缺点则是:它只支持 GET 请求而不支持 POST 等其它类型的 HTTP 请求;它只支持跨域 HTTP 请求这种情况,不能解决不同域的两个页面之间如何进行 JavaScript 调用的问题。
JsonP 的使用:
搭建跨域场景
需求:
1)创建两个 web 工程,名称为 jsonDemo1(8080)、jsonDemo2(9090)
2)jsonDemo1 中提供一个 index.jsp。
3)在 jsonDemo1 的 index.jsp 中通过 Jquery 的 Ajax 跨域请求 jsonDemo2
4)jsonDemo2 中使用 springMVC 处理请求,返回一个 json 对象
5)在 jsonDemo1 中将返回的结果插入到 index.jsp 中
创建项目
jsonDemo1
jsonDemo2
使用 JsonP 解决跨域:
Ajax 跨域请求时会出现异常
在 ajax 中请求方式有所改变
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2019/10/11
Time: 9:18
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>首页</title>
<script type="text/javascript" src="/js/jquery-1.7.2.js"></script>
<script type="text/javascript">
$(function () {
$("#but").click(function () {
$.ajax({
type:"get",
url:"http://localhost:9090/user/findUser",
dataType:"jsonp",
jsonp:"callback",
success:function (data) {
alert(data);
var str="";
for (i=0;i<data.length;i++){
str+=data[i].userid+" "+data[i].username+" "+data[i].userage;
}
$("#sp").html(str);
}
})
})
})
</script>
</head>
<body>
<h1>欢迎</h1>
<span id="sp"></span>
<input type="button" value="ok" id="but">
</body>
</html>
请求的 Controller 需要改变(SpringMVC 对 JsonP 的支持)
package com.bjsxt.web.controller;
import com.bjsxt.comments.JsonUtils;
import com.bjsxt.pojo.Users;
import org.springframework.http.converter.json.MappingJacksonValue;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.ArrayList;
import java.util.List;
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/findUser")
@ResponseBody
public Object findUser(String callback){
Users users1=new Users(1,"admin",20);
Users users2=new Users(2,"zhangsan",20);
Users users3=new Users(3,"lisi",20);
List<Users> list= new ArrayList<>();
list.add(users1);
list.add(users2);
list.add(users3);
//json转换
MappingJacksonValue mv=new MappingJacksonValue(list);
mv.setJsonpFunction(callback);
/*String json=JsonUtils.objectToJson(list);*/
return mv;
}
}