0
点赞
收藏
分享

微信扫一扫

关于跨域问题

琛彤麻麻 2022-04-27 阅读 70
javascript

JSONP介绍

JSONP(JSON with Padding)是为了跨域获取资源而产生的一种非官方的技术手段,它利用的是script标签的src属性不受同源策略影响的特性,使网页可以得到从其他来源动态产生的json数据,因此可以用来实现跨域读取数据。

原理

JSONP的最基本的原理是:动态添加一个script标签,而script标签的src属性是没有跨域的限制的。
动态创建script标签,请求后端地址,后端经过处理,返回结果封装在callback参数里面,格式为callback参数(json)。
优点:浏览器兼容性好
缺点:只支持get请求

使用Script模式

var url = "http://localhost:8080/getPhoneNum";

function jsonpByScript() {
	// 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码)
	var newUrl = url + "?callback=pcall";
	// 创建script标签,设置其属性
	var script = document.createElement('script');
	script.setAttribute('src', newUrl);
	// 把script标签加入head,此时调用开始
	document.getElementsByTagName('head')[0].appendChild(script);
}

//查询结果后的回调函数
function pcall(data) {
	console.info("pcall", data);
}

jsonpByScript();

// 打印结果为
pcall {phoneNum: Array(2)}

// 请求返回结果
pcall({"phoneNum":["17011112222","17022223333"]})

浏览器显示信息

General
Request URL: http://localhost:8080/getPhoneNum?callback=pcall
Request Method: GET
Status Code: 200
Remote Address: [::1]:8080
Referrer Policy: strict-origin-when-cross-origin

Response Headers
Date: Tue, 26 Apr 2022 10:13:15 GMT
Transfer-Encoding: chunked

Request Headers
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Connection: keep-alive
Host: localhost:8080
Referer: http://127.0.0.1:8848/
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="98", "Google Chrome";v="98"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Sec-Fetch-Dest: script
Sec-Fetch-Mode: no-cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36

使用Ajax模式

实际上还是使用script方式

//查询结果后的回调函数
function pcall(data) {
	console.info("pcall", data);
}

function jsonpByAjax() {
	$.ajax({
		url: url,
		type: "get",
		data: {},
		dataType: "jsonp",
		jsonp: "callback", //传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
		jsonpCallback: "pcall", //自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据
		success: function(data) { //先调用pcall,在调用success
			console.info("success", data);
		}
	})
}

jsonpByAjax();

// 打印结果
pcall {phoneNum: Array(2)}
success {phoneNum: Array(2)}
// 请求返回结果
pcall({"phoneNum":["17011112222","17022223333"]})
// 如果注释掉jsonpCallback: "pcall",结果样例
jQuery1830794611485514708_1650966351145({"phoneNum":["17011112222","17022223333"]})

浏览器显示信息

General
Request URL: http://localhost:8080/getPhoneNum?callback=pcall1650967838128
Request Method: GET
Status Code: 200
Remote Address: [::1]:8080
Referrer Policy: strict-origin-when-cross-origin

Response Headers
Date: Tue, 26 Apr 2022 10:10:38 GMT
Transfer-Encoding: chunked

Request Headers
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Connection: keep-alive
Host: localhost:8080
Referer: http://127.0.0.1:8848/
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="98", "Google Chrome";v="98"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Sec-Fetch-Dest: script
Sec-Fetch-Mode: no-cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36

后台Java代码

 try (PrintWriter writer = resp.getWriter();) {
     String callback = req.getParameter("callback");
     String jsonStr = "{\"phoneNum\":[\"17011112222\",\"17022223333\"]}";
     writer.print(callback + "(" + jsonStr + ")");
     writer.flush();
 } catch (Exception e) {
     e.printStackTrace();
 }

CORS(Cross-Origin Resource Sharing)跨域资源共享

CORS需要浏览器和服务器同时支持。目前,除了低于IE10浏览器不支持,多数浏览器都支持该功能。

整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX跨域请求,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨域访问。

两种请求

浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。
只要同时满足以下两大条件,就属于简单请求。

1) 请求方法是以下三种方法之一:
	HEAD
	GET
	POST2HTTP的头信息不超出以下几种字段:
	Accept
	Accept-Language
	Content-Language
	Last-Event-ID
	Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

详情请参考跨域资源共享 CORS 详解

网页代码

var url = "http://localhost:8080/getPhoneNum2";

function ajax() {
	$.ajax({
		url: url,
		type: "get",
		data: {},
		dataType: "JSON",
		success: function(data) {
			console.info("success", data);
		}
	})
}

ajax();

// 打印结果
success {phoneNum: Array(2)}
// 请求返回结果
{"phoneNum":["17011112222","17022223333"]}

浏览器显示信息

General
Request URL: http://localhost:8080/getPhoneNum2
Request Method: GET
Status Code: 200
Remote Address: [::1]:8080
Referrer Policy: strict-origin-when-cross-origin

Response Headers
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Content-Type, Cache-Control, Expires, X-E4M-With,userId,token
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Origin: http://127.0.0.1:8848
Access-Control-Max-Age: 0
Content-Type: application/json;charset=UTF-8
Date: Tue, 26 Apr 2022 11:45:27 GMT
Transfer-Encoding: chunked

Request Headers
Accept: application/json, text/javascript, */*; q=0.01
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Connection: keep-alive
Host: localhost:8080
Origin: http://127.0.0.1:8848
Referer: http://127.0.0.1:8848/
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="98", "Google Chrome";v="98"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36

后台Java代码

// resp.setHeader("Access-Control-Allow-Origin", "*");
resp.setHeader("Access-Control-Allow-Origin", "http://127.0.0.1:8848");
resp.setHeader("Access-Control-Allow-Methods", "GET, POST");
resp.setHeader("Access-Control-Max-Age", "0");
resp.setHeader("Access-Control-Allow-Headers",
        "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Content-Type, Cache-Control, Expires, X-E4M-With,userId,token");
resp.setHeader("Access-Control-Allow-Credentials", "true");
resp.setHeader("Content-type", "application/json; charset=UTF-8");
try (PrintWriter writer = resp.getWriter();) {
    String jsonStr = "{\"phoneNum\":[\"17011112222\",\"17022223333\"]}";
    writer.print(jsonStr);
    writer.flush();
} catch (Exception e) {
    e.printStackTrace();
}
举报

相关推荐

0 条评论