天天看点

前端跨越原理及解决办法第3章:前端跨越原理及解决办法

第3章:前端跨越原理及解决办法

3.1同源策略

  • 同源策略(Same-Origin Policy) 最早由 Netscape 公司提出,是浏览器的一种安全策略。

浏览器就会处于安全问题,提出的同源策略。

(过去的钓鱼的网站,里面的东西和正常的网页一样,除了网址,,获取你的用户名,密码来

iframe可以嵌套网页,钓鱼网站,分辨不了账户名的真假,都会跳出登录成功。)

  • 同源: 协议、域名、端口号 必 须完全相同。
  • 违背同源策略就是跨域。

因为我们的服务器有多个,所以肯定会要跨域

3.2如何解决跨域

3.2.1 解决方案:JSONP

1) JSONP是什么?
    JSONP(JSON with Padding),是一个非官方的跨域解决方案,纯粹凭借程序员的聪明才智开发出来,只支持get请求。
    
优点:兼容性很好。

2) JSONP怎么工作的?
   在网页有一些标签天生具有跨域能力,比如:img link iframe script。
   JSONP就是利用script标签的跨域能力来发送请求的。

3)JSONP的使用
    1.动态的创建一个script标签
	  var script = document.createElement("script");
    2.设置script的src,一定要设置回调函数
      script.src = "http://localhost:3000/testAJAX?callback=abc";
	  function abc(data) {
        alert(data.name);
	  };
    3.将script添加到body中
     document.body.appendChild(script);
    4.服务器中路由的处理
     router.get("/testAJAX" , function (req , res) {
		console.log("收到请求");
		var callback = req.query.callback;
        var obj = {
			name:"孙悟空",
			age:18
		}
		res.send(callback+"("+JSON.stringify(obj)+")");
	});

4) jQuery中的Jsonp
     	
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
  <button id="btn">按钮</button>
  <ul id="list"></ul>
  <script type="text/javascript" src="./jquery-1.12.3.js"></script>
  <script type="text/javascript">
    window.onload = function () {
      var  btn =document.getElementById("btn");   
      btn.onclick = function () {
        $.getJSON("http://api.douban.com/v2/movie/in_theaters?callback=?",function (data) {
          console.log(data);
          //获取所有的电影的条目
          var subjects = data.subjects;
          //遍历电影条目
          for(var i=0 ; i<subjects.length ; i++){
            $("#list").append("<li>"+
              subjects[i].title+"<br />"+
              "<img src=\""+subjects[i].images.large+"\" >"+
              "</li>");
          }
        });
      }
    }
  </script>
</body>
</html>      
           

3…2.2 Jsonp案例:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<button id="btn">按钮</button>
<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
<script type="text/javascript">

  $('#btn').click(function () {
    /*
      JSONP:
        跨域:进行同源策略的检查,浏览器的ajax引擎检查的。
              跨域只有ajax请求可能产生,别的请求script、img、video是不会产生跨域的

        原理:利用script天然可以跨域的特性进行跨域的

        优点:兼容性极好
        缺点:只能发GET请求
     */
    // 1. 创建script标签
    /*const script = document.createElement('script');
    // 2. 设置script src属性,设置请求地址?查询字符串。请求方式默认是get
    script.src = 'http://localhost:3000/ajax?name=jack&callback=fn';
    // 3. 设置请求成功回调函数
    window.fn = function (data) {
      // 响应成功的数据
      console.log(data);
    };
    // 4. 将script标签添加到页面上,才能生效
    document.body.appendChild(script);*/

    $.getJSON('http://localhost:3000/ajax?callback=?', function (data) {
      // 响应成功的数据
      console.log(data);
    })
  })

</script>
</body>
</html>
           

3.2.3 CORS

cors:abbr. 连续运行参考站(ko 儿 s )

  1. CORS是什么?

因为jsonp太麻烦,而且只能发get请求,所以:

CORS(Cross-Origin Resource Sharing),跨域资源共享。CORS是官方的跨域解决方案,它的特点是不需要在客户端做任何特殊的操作,完全在服务器中进行处理,支持get和post请求。

  1. CORS怎么工作的?

CORS是通过设置一个响应头来告诉浏览器,该请求允许跨域,浏览器收到该响应以后就会对响应放行。

  1. CORS的使用

主要是服务器端的设置:

router.get("/testAJAX" , function (req , res) {

​ //通过res来设置响应头,来允许跨域请求

​ //res.set(“Access-Control-Allow-Origin”,“http://127.0.0.1:3000”);

​ res.set(“Access-Control-Allow-Origin”,"*");

​ res.send(“testAJAX返回的响应”);

});

3.3.4 CORS案例:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<button id="btn">按钮</button>
<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
<script type="text/javascript">

  /*
    cors:
      优点:能支持任意的请求方式
      缺点:兼容性稍差
   */
  $('#btn').click(function () {
    // 发送ajax请求
    $.get('http://localhost:3000/cors', {name: 'jack', age: 18}, function (data) {
      console.log(data);
    });
  })
</script>
</body>
</html>



const express = require('express');
const app = express();

app.use(express.static('public'));
// 解析请求体参数:只能解析采用urlencoded编码
app.use(express.urlencoded({extended: true}));
// 解析请求体参数:只能解析采用json编码
app.use(express.json());

app.get('/ajax', (req, res) => {
  // 函数名:fn
  const { callback } = req.query;

  const data = {name: 'tom', age: 55};

  // 返回响应  fn({name: 'tom', age: 55})   callback(json)

  res.send(`${callback}(${JSON.stringify(data)})`);
});

app.post('/ajax', (req, res) => {
  console.log(req.body);

  res.json({name: 'tom', age: 20});
});

app.get('/cors', (req, res) => {
  // 设置响应头
  const safeUrl = ['http://localhost:63342', 'https://www.baidu.com'];
  // 允许所有地址跨域
  // res.set('access-control-allow-origin', '*');
  const url = req.headers.origin;
  console.log(url);
  if (safeUrl.includes(url)) {
    // 允许单个地址跨域
    res.set('access-control-allow-origin', url);
    res.set('access-control-allow-headers', 'X-Juejin-Src,X-Juejin-Client,X-Juejin-Uid,X-Juejin-Token');
    res.set('Access-Control-Allow-Credentials', true);
    res.set('Access-Control-Allow-Methods', 'GET, PUT, POST, DELETE, HEAD');
    res.set('Access-Control-Max-Age', 86400);
  }

  /*
    Access-Control-Allow-Credentials: true  允许预检请求
      当请求方式是POST PUT DELETE,或者请求头中有特殊字段(X-Juejin-Src),这个时候浏览器会先发送一个预检请求(请求方式是options)
      预检请求: 检查当前请求是否能进行跨域。  如果不行,就不在发请求了。 如果行,在发送真正的请求
    Access-Control-Allow-Headers: X-Juejin-Src,X-Juejin-Client,X-Juejin-Uid,X-Juejin-Token
      允许以上这些字段跨域跨域(如果请求头中的特殊字段不在包含范围,就不允许跨域)
    Access-Control-Allow-Methods: GET, PUT, POST, DELETE, HEAD
      允许怎么样请求方式跨域跨域
    Access-Control-Allow-Origin: https://juejin.im
      允许哪些地址可以跨域
    Access-Control-Max-Age: 86400
     预检请求跨域缓存
   */
  res.send('hello cors');
});

app.listen(3000, (err) => {
  if (!err) console.log('服务器启动成功了~');
  else console.log(err);
});