天天看點

前端跨越原理及解決辦法第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);
});