同源策略,跨域请求处理

跨域访问 - 跨域请求

同源策略

适用于浏览器的一种资源访问策略;

同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。

浏览器为什么使用同源策略

同源策略,它是由Netscape提出的一个著名的安全策略。现在所有支持 JavaScript 的浏览器都会使用这个策略。所谓同源是指,域名/IP/主机,协议,端口相同。在浏览器的js中,通过代码(脚本)去访问网络资源的时候会应用该策略

假设在a页面的地址是(http://www.baidu.com/a.html),

那么a页面所在的源信息是:协议:http,域名:baidu.com,端口:80

那么在这个页面中通过js去访问另外一个资源:(http://www.baidu.com/b.html)。

那么这个时候会使用同源策略进行检测,上面两个页面的协议域名端口是相同的,那么这时候一个同源请求,如果访问的是:(http://www.qq.com/b.html),那么很明显这个时候就是非同源请求,这个时候,请求会受到一定的限制。

以 http://www.baidu.com/a.html 为例,以下都是非同源的:
  • http://www.qq.com/b.html
  • http://www.baidu.com:8080/b.html
  • http://baike.baidu.com/b.html
  • https://www.baidu.com/b.html
  • http://baidu.com/b.html 注意:www其实也是一个二级子域名,只是习惯把www和顶级域名绑定在一起去使用而已

AJAX请求

我们使用ajax去请求资源的时候,就被使用同源策略进行检测,同源策略是适用于浏览器的,也就是说如果我们发送了一个跨域的请求,服务器是能接收到并能处理和返回的,但是浏览器在接收到返回数据以后,会比较他们的域是否相同,如果不相同,拒绝接收和处理!

解决办法

Access-Control-Allow-Origin

当浏览器接收到非同源数据的时候,会首先去头信息看Access-Control-Allow-Origin字段里面的值,如果当前域在Access-Control-Allow-Origin里面有包含,则忽略同源策略

例如我们有给服务器分别为localhost:7777localhost:8888

当我们在端口8888情况下访问7777的数据时,因为同源策略检测,ajax请求就会直接报错,这时我们需要在被请求也就是8888的后端里设置头信息res.setHeader('Access-Control-Allow-Origin',"localhost:7777"),

感觉类似白名单一样,如果想所有不同源的端口都访问可以把里面的值改为通配符(*

后端代理

后端之间互相访问请求不同源的是不会有同源策略,因为同源策略是基于浏览器来产生的,所以我们可以让自己的服务器后端去访问请求跨域的地址,然后把结果再传给我们,这样就类型一种代理的行为

//nodejs中axios插件 就集成了服务端去发送请求方法
app.get('/data', (req, res) => {

    /*
    * 通过服务端去发送请求
    * */
    axios.get('http://localhost:8888/data').then( response => {
        //console.log(response.data);
        res.send(response.data);
    } );
});

//然后ajax在去接收responseText
var xhr = new XMLHttpRequest();

xhr.open('get', 'http://localhost:8888/data', true);

xhr.onload = function() {
  console.log(this.responseText);
};

xhr.send();
jsonp

为了解决同一个接口的调用不同的函数,实现不同的逻辑,那么后端输出的函数名不再固定,而是由前端通过get方式传入一个指定的参数,比如callback,后端根据callback传入的值,输出不同的函数调用名

弊端:只能通过get方式

注意:一个api接口是否能够通过jsonp的方式去使用,还要看该接口输出的数据格式,知否能够被script标签加载后被js所执行

具体方法:通过创建一个script标签,地址指向第三方的API网址,例如被请求方的数据是:

app.get('/list', (req, res) => {

    let callback = req.query.callback || 'fn';
    let type = req.query.type || 'teachers';

    let data = {
        teachers: ['Leo','Motao', 'zMouse'],
        students: ['张三','李四', '王五', '赵六', '田七']
    };

    res.send(callback + '('+ JSON.stringify(data[type]) +')');
});

我们通过创建一个script标签,就不会收到同源策略的影响,其中可以通过一个callback函数来接受数据,可以是一个约定的函数名,或者通过地址来传递,这样我们前台在拿数据就可以通过函数名来拿到手

document.onclick = function() {
  var scriptElement = document.createElement('script');
  scriptElement.src = 'http://localhost:7777/list?callback=fn2&type=students';
  //需要什么信息就传入什么约定好的名字
  document.body.appendChild(scriptElement);
};
function fn(data) { //地址中传入的callback名
  var html = '';
  data.forEach( item => {
    html += '
  • '+ item +'
  • '; } ); uls[0].innerHTML = html; }

    你可能感兴趣的:(同源策略,跨域请求处理)