Node.JS解决跨域问题 CORS策略 同源策略介绍 http模块学习 axios使用

759 阅读4分钟

本文已参与[新人创作礼]活动, 一起开启掘金创作之路。

场景介绍

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

在1995年,同源策略由 Netscape 公司引入浏览器。目前,所有浏览器都实行这个策略。

所谓同源指的是三个相同:

  • 协议相同。 例如:都是http协议
  • 域名相同。 例如:ip地址一样
  • 端口相同。 例如:端口号,不能一个8888,一个8080

如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。

举个栗子(eg):

image.png

image.png

image.png

意义:同源策略是浏览器的行为,是为了保护本地数据不被JavaScript代码获取回来的数据污染,因此拦截的是客户端发出的请求回来的数据接收,即请求发送了,服务器响应了,但是无法被浏览器接收。同源策略是为了保证用户信息的安全,防止恶意的网站窃取数据。

演示一个跨域的例子

模拟服务端 后台接口

使用http模块快速搭建后台:

var http = require('http')
// 模拟的数据,到时候JSON.stringify数据转换一下返回给客户端
var msg = {
    "name" : "狗彬",
    "school": "厦门理工学院",
    "age" : "23",
    "job" : "虚假的vue前端工程师"
}

// 创建服务器
http.createServer( (req, res) =>{  
    // 解析请求,包括文件名
    var ReqPath = req.url;
    console.log(ReqPath);
    // 编写响应头(不写浏览器不识别)
    res.writeHead(200, { 'Content-Type': 'application/json', 'X-Powered-By': 'bacon' });
    // 发送响应数据
    res.end(JSON.stringify(msg)); 
 }).listen(8888);
  
 // 控制台会输出以下信息
 console.log('您的http服务启动在  http://127.0.0.1:8888/');
node 服务端.js

image.png

这里我们直接 给它把服务跑起来。注意:我们服务端后台接口的端口号是8888。

试着用8888端口访问,发现一切正常

image.png

模拟“客户端”

我们新建一个html文件,作为“客户端”。当然,严格意义来讲,我们这应该属于B/S模式,浏览器/服务器模式。

这里我用<script>标签来引入axios。对,ajax请求我用axios来发起。

同时,我用VScode的open with liveServer插件 模拟网页放在服务器来访问的情景。(网页文件一定要在服务器被请求回来,不然不能发起ajax请求)

来,话不多说,直接上我们“客户端”的代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>node 后端接口跨域解决办法</title>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
    <input type="button" value="发起请求" onclick="getMsg()">
    <p id="Pmsg"></p>
</body>
<script>
    function getMsg () {
        axios({
		method: 'get',//提交方法
		url: 'http://127.0.0.1:8888/',//提交地址
		}).then((res) => {
          // 成功
          console.log("成功发起请求,以下是后端接口返回的数据");
		  console.log(res);

          var Pmsg =  document.getElementById("Pmsg");
          Pmsg.innerHTML = JSON.stringify(res);
		}).catch(err => {
          // 失败
          console.log("请求失败,打印失败信息")
          console.log(err);

          var Pmsg =  document.getElementById("Pmsg");
          Pmsg.innerHTML = JSON.stringify(err);
   })
    }
</script>
</html>

代码写完,直接在VScode右键 选择open with liveServer

image.png

可以看到,VScode随机在本机:5500端口给我们打开了网页,由于8888与5500端口不同,所以我们是违反了同源策略的。

多说多嗦无意义,我们直接碰一碰按钮看看反应:

image.png

看见了吧,硕大的 has been blocked by CORS policy

这!

就是!!

浏览器跨域!!!

吓不吓人,怕不怕!!!!

别怕,年轻人,有彬哥在,彬哥手把手教你破除

image.png

设置响应头

Access to XMLHttpRequest at 'http://127.0.0.1:8888/' from 
origin 'http://127.0.0.1:5500' has been blocked by CORS policy: 
No 'Access-Control-Allow-Origin' header is present on the requested resource.

仔细分析之前的报错提示,可以看到里面提到的 'Access-Control-Allow-Origin'

这个东西有妙用,具体来说: Access-Control-Allow-OriginHTML5中定义的一种解决资源跨域的策略。

通过服务器端返回带有Access-Control-Allow-Origin标识的response header,我们在响应头response里面设置一下,就可以实现跨域访问资源。

设置 'Access-Control-Allow-Origin' 解决跨域

响应头中可以携带一个Access-Control-Allow-Origin字段,其中origin参数的值指定了允许访问该资源的外域URL。

设置只允许来自掘金的请求

// 只允许来自 掘金的请求 
res.setHeader('Access-Control-Allow-Origin','https://juejin.cn/')

允许所有域的请求

// 通配符 * 允许来自所有域的请求 
res.setHeader('Access-Control-Allow-Origin','*')

虽然允许来自所有域的请求很危险,但是图方便省事的话,确实是个好东西。

具体代码解决之前的demo跨域问题

修改服务端代码:

var http = require('http')

var msg = {
    "name" : "狗彬",
    "school": "厦门理工学院",
    "age" : "23",
    "job" : "虚假的vue前端工程师"
}

// 创建服务器
http.createServer( (req, res) =>{  
    // 解析请求,包括文件名
    var ReqPath = req.url;
    console.log(ReqPath);
    // 通配符 * 允许来自所有域的请求 
    res.setHeader('Access-Control-Allow-Origin','*')
    // 编写响应头(不写浏览器不识别)
    res.writeHead(200, { 'Content-Type': 'application/json', 'X-Powered-By': 'bacon' });
    // 发送响应数据
    res.end(JSON.stringify(msg)); 
 }).listen(8888);
  
 // 控制台会输出以下信息
 console.log('您的http服务启动在  http://127.0.0.1:8888/');

运行客户端:

image.png

好,非常的ok