1、同源策略
同源策略即:同一协议,同一域名,同一端口号。当其中一个不满足时,我们的请求即会发生跨域问题。跨域的出现是为了保证浏览器数据的安全 。
2、Jsonp
(1)原理
目前我们知道的网络请求的形式:
- 地址栏:地址栏输网址==>没有跨域限制 默认是get请求
- ajax:无论工具库还是原生代码 都有跨域限制 get/post请求 请求的数据自己使用(xhr.responseText)
- a link :href==>没有跨域限制 默认是get请求 它的请求功能是浏览器做的 而且使用数据的功能也是浏览器做的
- form:action==>没有跨域限制 get/post请求 它的请求功能是浏览器做的 而且使用数据的功能也是浏览器做的
- img:src 没有跨域限制 默认是get请求 会启用绘制引擎去按照img资源的编码进行渲染
- script:src 没有跨域限制 默认是get请求,会启动js引擎去执行js代码,如果返回的数据的编码不是标准的js编码,就运行不了;如果返回的数据的编码是标准的js编码,就正常运行。
我们可以看到,不管是script标签的src还是img标签的src,或者说link标签的href他们没有被同源策略所限制,jsonp就是使用同源策略这一“漏洞”,实现的跨域请求(这也是jsonp跨域只能用get请求的原因所在)。
(2)实现
前端提前声明一个全局函数,比如show,利用script的src去加载后端的jsonp接口并且在src中拼接一个callback=show参数
function fn() {
window.show = function(arg) {
console.log(arg);
}
let sr = document.createElement('script');
sr.src = "http://localhost:81/mydata?callback=show";
document.body.appendChild(sr);
}
//jquery中的jsonp
function jqfn() {
//方法一:
let url = "http://localhost:81/mydata?callback=?"
$.getJSON(url, (data) => {
console.log(data);
})
//方法二:
$.ajax({
url: "http://localhost:81/mydata",
dataType: "jsonp", //预期服务器返回的数据类型
jsonp: "callback",
// jsonpCallback: "show2",//可填(系统默认帮我们填)
success: function(data) {
console.log(data);
}
})
}
后端解析前端传过来的参数取出callback字段,当做一个函数名后端在给前端传输数据时,把json数据放在这个函数的调用里 ,然后把整个字符换传给前端
module.exports = {
mydata(req, res) {
console.log(req.query.callback); //show
res.end(`${req.query.callback}({name: "kersen",age:20})`);
}
}
3、CORS跨域资源共享
在后端代码中设置响应头,一般设置三个属性:
- Access-Control-Allow-Origin
- Access-Control-Allow-Methods
- Access-Control-Allow-Headers
也可以只设置Access-Control-Allow-Origin属性。完整代码:
module.exports = {
mydata(req, res) {
console.log(req.query);
//设置允许跨域的域名,*代表允许任意域名跨域
res.setHeader("Access-Control-Allow-Origin", "*");
//允许的header类型
// res.setHeader("Access-Control-Allow-Methods", "*");
//跨域允许的请求方式
// res.setHeader("Access-Control-Allow-Headers", "*");
res.json({name: "kersen",age:25});
}
}
4、代理服务器
代理服务器通过request第三方模块去请求要访问的服务器的ajax接口(没有跨域限制,因为同源策略的限制只存在浏览器中,到了服务器端就没有这个限制了),把数据请求到代理服务器,我们再去访问代理服务器中的数据实现跨域。
//前端
function fn() {
$.ajax({
url:"http://localhost:81/delegate1",
success:function(data){
console.log(JSON.parse(data));
}
})
}
//服务器端
let request = require("request");
module.exports = {
delegate1(req, res) {
let url = "https://api.weibo.com/2/statuses/home_timeline.json?access_token=2.00ZmCkcDlel8HDd856f9b9ccsVwsYD"
request(url, (err, statusts, body) => {
res.end(body);
})
}
}
5、oAuth授权开发
比如我们想使用第三方企业的数据,别人都是ajax接口,我们可以利用代理服务器(爬虫)去访问,但是这是违法的,如果要合法,我们就需要使用oAuth授权开发
以新浪微博为例:
-
成为某公司的普通会员
-
把普通会员升级成为开发者账号,登录”新浪微博开发平台“
-
oAuth授权(2.0)
(1)用开发者账号申请应用:点击移动应用->立即接入->创建应用->获取到app-key:xxxxxx和App Secret:xxxxxx->高级信息->获取到授权回调页:https://www.baidu.com/index.html
(2)用app-key app-secret 去请求用户授权(用户输入新浪账号密码给新浪):点击文档->微博API->请求授权->浏览器输入https://api.weibo.com/oauth2/authorize?client_id=xxxxxx&redirect_uri=https://www.baidu.com/index.html->授权进入页面,在网址上面得到一个code码
(3)用code码去换取access_token:获取授权->获得url:https://api.weibo.com/oauth2/access_token?client_id=xxxxxx&client_secret=xxxxxxx&grant_type=authorization_code&code=xxxxxx&redirect_uri=https://www.baidu.com/index.html->创建index.js并运行:
let request = require("request");
let url =
"https://api.weibo.com/oauth2/access_token?client_id=xxxxxx&client_secret=xxxxxxx&grant_type=authorization_code&code=xxxxxx&redirect_uri=https://www.baidu.com/index.html";
request.post(url, (err, statusts, body) => {
console.log(body)
})
得到: {"access_token":"xxxxxx","remind_in":"xxxx","expires_in":xxxx,"uid":"xxxx","isRealName":"true"},获得access_token:xxxxxx
(4)用这个token去新浪公司请求anyone 就可以做自己的产品