跨域、CORS、JSONP知识总结

1.同源策略

1.1源

源(origin)就是协议、域名和端口号,我们在浏览器里面可以用window.origin知道.

1.2同源

若地址里面的协议、域名和端口号均相同则属于同源,比如
https://www.baidu.com/与https://www.baidu.com/.

1.3同源策略的定义

如果JS运行在源A里面,只能获取源A的数据,不能获取源B的数据,这是浏览器的规定.

1.3.2同源策略的意义

这样是为了保护隐私,因为如果能同源的话黑客随时可以黑你的电脑,可怕......

2CORS(跨源资源共享)

2.1CORS的定义

跨源资源共享 (CORS) (或通俗地译为跨域资源共享)是一种基于HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其它origin(域,协议和端口),这样浏览器可以访问加载这些资源。跨源资源共享还通过一种机制来检查服务器是否会允许要发送的真实请求,该机制通过浏览器发起一个到服务器托管的跨源资源的"预检"请求。在预检中,浏览器发送的头中标示有HTTP方法和真实请求中会用到的头。

2.2如何去设置CORS

1.Access-Control-Allow-Origin: *表明,该资源可以被任意外域访问
2.Access-Control-Allow-Origin: http://foo.example,表示就是该网站可以访问
举例说明:
frank.com想访问qq.com里面的json文件

image.png

如果不设置CORS的话,则是这个报错
image.png

如果设置CORS的话,我们可以看到正常的运行代码
image.png

response.setHeader('Access-Control-Allow-Origin','http://frank.com:9999')

3.JSONP

3.1JSONP和JSON的关系

没有任何关系

3.2JSONP用在什么地方

当在比较老的浏览器里面不能用CORS,这个时候可以用JSONP, 主要就是利用了 script 标签的src没有跨域限制来完成的,主要是写一个回调函数,参数就是从其他源拿的数据.
举例说明(还是qq.com和frank.com两个网站来模拟):
qq.com后台的服务器

var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]

if(!port){
  console.log('请指定端口号好不啦?\nnode server.js 8888 这样不会吗?')
  process.exit(1)
}

var server = http.createServer(function(request, response){
  var parsedUrl = url.parse(request.url, true)
  var pathWithQuery = request.url 
  var queryString = ''
  if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
  var path = parsedUrl.pathname
  var query = parsedUrl.query
  var method = request.method

  /******** 从这里开始看,上面不要看 ************/

  console.log('有个傻子发请求过来啦!路径(带查询参数)为:' + pathWithQuery)

  if(path === '/index.html'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    response.write(fs.readFileSync('index.html'))
    response.end()
  } else if(path === '/qq.js'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
    response.write(fs.readFileSync('qq.js'))
    response.end()
  }else if(path ==='/friends.json'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/json;charset=utf-8')
    console.log(request.headers['referer'])
    response.setHeader('Access-Control-Allow-Origin','http://frank.com:9999')
    response.write(fs.readFileSync('friends.json'))
    response.end()
  }else if(path ==='/friends.js'){
    if(request.headers['referer'].indexOf('http://frank.com:9999')===0){
      response.statusCode = 200
      response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
      const string=fs.readFileSync('friends.js').toString()
      const data=fs.readFileSync('friends.json').toString()
      const string2=string.replace('{{data}}',data).replace('{{xxx}}',query.callback)
      response.write(string2)
      response.end()
    }else{
      response.statusCode=404
      response.end()
    };
  }else {
    response.statusCode = 404
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    response.write(`你输入的路径不存在对应的内容`)
    response.end()
  }

  /******** 代码结束,下面不要看 ************/
})

server.listen(port)
console.log('监听 ' + port + ' 成功\n请用在空中转体720度然后用电饭煲打开 http://localhost:' + port)

前端的代码




    
    
    我是黑客


    你好黑客
    


JSONP代码

function jsonp(url){
    return new Promise((resolve,reject)=>{
        const random='frankJSONPCallbackName'+Math.random()
        window[random]=(data)=>{
            resolve(data);  
        }
        const script=document.createElement('script')  
        script.src=`${url}?callback=${random}` 
        script.onload=()=>{
            script.remove;
        };
      script.onerror=()=>{
       reject();
      }
        document.body.appendChild(script)
    })
}
jsonp("http://qq.com:8888/friends.js").then(data => {
    console.log(data);
  });

效果


image.png

3.3优缺点

1.优点:它的兼容性更好,在更加古老的浏览器中都可以运行
2.缺点:它只支持GET请求而不支持POST等其它类型的HTTP请求,同时jsonp在调用失败的时候不会返回各种HTTP状态码.
本文中的全部代码已经上传到 https://zhuzikaihua888.github.io/-kuayu-1/,大家可以下载来进行模拟
本文为本人的原创文章,著作权归本人和饥人谷所有,转载务必注明来源.

你可能感兴趣的:(跨域、CORS、JSONP知识总结)