Web 前端开发 让前端飞程序员

2017.12.11-学习笔记:聊聊同源跨域 Jsonp、COR

2017-12-11  本文已影响73人  bixin

同源策略

跨域

跨域解决办法:Jsonp、CORS、Nginx反向代理

script src 属性 进行 get 请求 js 文件, 不受同源策略限制
script 标签 只是在请求数据, js文本, php响应的也是js文本,所以, src 也可以引入 php 文件
浏览器会将获取过来的文本当成 js 来执行

1.服务端JSONP格式数据
如客户想访问 : http://www.jsonp.com/try/ajax/jsonp.php?jsonp=callbackFunction
假设客户期望返回JSON数据:["customername1","customername2"]。
真正返回到客户端的数据显示为: callbackFunction(["customername1","customername2"])。
服务端文件jsonp.php代码为:

<?php
header('Content-type: application/json');
//获取回调函数名
$callback = $_GET['callback'];
//json数据
$json_data = '["customername1","customername2"]';
//输出jsonp格式的数据
echo $callback . "(" . $json_data . ")";
?>

2.客户端实现 callbackFunction 函数

<script type="text/javascript">
  function callbackFunction(result, methodName) {
    var html = '<ul>';
    for (var i = 0; i < result.length; i++) {
      html += '<li>' + result[i] + '</li>';
    }
    html += '</ul>';
    document.getElementById('divCustomers').innerHTML = html;
  }
</script>

3.客户端页面完整代码

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>JSONP 实例</title>
</head>

<body>
  <div id="divCustomers"></div>
  <script type="text/javascript">
    function callbackFunction(result, methodName) {
      var html = '<ul>';
      for (var i = 0; i < result.length; i++) {
        html += '<li>' + result[i] + '</li>';
      }
      html += '</ul>';
      document.getElementById('divCustomers').innerHTML = html;
    }
  </script>
  <script type="text/javascript" src="http://www.jsonp.com/try/ajax/jsonp.php?callback=callbackFunction"></script>

<!-- script标签可以是动态生成,放到事件中可以触发事件才获取数据
    // 动态创建 script 标签, 请求数据
    var script = document.createElement("script");
    // 设置src请求数据
    script.src = "http://www.jsonp.com/try/ajax/jsonp.php?callback=callbackFunction";
    // 将 script 添加到 头部中去
    document.head.appendChild( script );-->
</body>

</html>

4.jQuery 使用 JSONP

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>JSONP 实例</title>
  <script src="http://cdn.static.runoob.com/libs/jquery/1.8.3/jquery.js"></script>
</head>

<body>
  <div id="divCustomers"></div>
  <script>
    $.getJSON("http://www.jsonp.com/try/ajax/jsonp.php?callback=?", function(data) {

      var html = '<ul>';
      for (var i = 0; i < data.length; i++) {
        html += '<li>' + data[i] + '</li>';
      }
      html += '</ul>';

      $('#divCustomers').html(html);
    });
  </script>
</body>

</html>
// 原生ajax

var xhr = new XMLHttpRequest(); // IE8/9需用window.XDomainRequest兼容
// 前端设置是否带cookie
xhr.withCredentials = true;
xhr.open('post', 'http://www.domain2.com:8080/login', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('user=admin');
xhr.onreadystatechange = function() {
  if (xhr.readyState == 4 && xhr.status == 200) {
    alert(xhr.responseText);
  }
}

-------------------------

// jQuery

$.ajax({
  ...
  xhrFields: {
    withCredentials: true // 前端设置是否带cookie
  },
  crossDomain: true, // 会让请求头中包含跨域的额外信息,但不会含cookie
  ...
});

2.后台设置

  /*
   * 导入包:import javax.servlet.http.HttpServletResponse;
   * 接口参数中定义:HttpServletResponse response
   */
  response.setHeader("Access-Control-Allow-Origin", "http://www.domain1.com"); // 若有端口需写全(协议+域名+端口)
  response.setHeader("Access-Control-Allow-Credentials", "true");
#proxy服务器
server {
  listen 81;
  server_name www.domain1.com;
  location / {
    proxy_pass http: //www.domain2.com:8080; #反向代理
    proxy_cookie_domain www.domain2.com www.domain1.com;#修改cookie里域名
    index index.html index.htm;#当用webpack - dev - server等中间件代理接口访问nignx时, 此时无浏览器参与, 故没有同源限制, 下面的跨域配置可不启用
    add_header Access - Control - Allow - Origin http: //www.domain1.com; #当前端只跨域不带cookie时,可为*
    add_header Access - Control - Allow - Credentials true;
  }
}

1.前端设置:

var xhr = new XMLHttpRequest();
// 前端开关:浏览器是否读写cookie
xhr.withCredentials = true;
// 访问nginx中的代理服务器
xhr.open('get', 'http://www.domain1.com:81/?user=admin', true);
xhr.send();

2.nodejs后台:

var http = require('http');
var server = http.createServer();
var qs = require('querystring');
server.on('request', function(req, res) {
  var params = qs.parse(req.url.substring(2));
  // 向前台写cookie
  res.writeHead(200, {
    'Set-Cookie': 'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly' // HttpOnly:脚本无法读取
  });
  res.write(JSON.stringify(params));
  res.end();
});
server.listen('8080');
console.log('Server is running at port 8080...');
module.exports = {
  devtool: 'cheap-module-source-map',
  entry: './app/js/index.js'
  output: {
    path: path.resolve(__dirname, 'dev'),
    // 所有输出文件的目标路径
    filename: 'js/bundle.js',
    publicPath: '/',
    chunkFilename: '[name].chunk.js'
  },
  devServer: {
    contentBase: path.resolve(__dirname, 'dev'),
    publicPath: '/',
    historyApiFallback: true,
    proxy: {
      // 请求到 '/device' 下 的请求都会被代理到 target: http://debug.xxx.com 中
      '/device/*': {
        target: 'http://debug.xxx.com',
        secure: false, // 接受 运行在 https 上的服务
        changeOrigin: true
      }
    }
  }
}



Knowledge changes the mind

上一篇 下一篇

猜你喜欢

热点阅读