前后端跨域解决方案

同源策略

最早由netscape公司提出,是浏览器的一种安全策略

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

常见跨域的解决方案

  • 后端设置相应响应头
  • 使用jsonp的方式处理(利用script标签不受跨域协议的影响)
  • 设置正向代理服务器的方式处理(利用服务器与服务器之间不受跨域协议的影响)
  • 设置nginx反向代理服务器的方式
  • webpack代理方案
  • gulp代理方案

问题描述

前端请求页面会出现跨域问题

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>Documenttitle>
head>

<body>
   <button>发送button>

   <script>
       let btn = document.getElementsByTagName('button')[0];

       btn.addEventListener('click', () => {

           let xml = new XMLHttpRequest();

           xml.open('get', 'http://127.0.0.1:2200', true);

           xml.timeout = 2000;

           xml.addEventListener('timeout', () => {
               xml.abort();
               console.error('请求超时');
           });

           xml.addEventListener('error', () => {
               console.error('请求错误');
           });

           xml.send(null);

           xml.addEventListener('readystatechange', () => {
               if (xml.readyState === 4) {


                   if (xml.status >= 200 && xml.status < 300 || xml === 304) {
                       console.log(xml.responseText);
                   }
               }
           });
       });
   script>
body>

html>

后端

const http = require('http');

const server = http.createServer();

server.on('request', (request, response) => {
    if (request.method === 'get') {
        response.end('get');
    } else {
        response.end('post');
    }
});

server.listen(2200, err => {
    err ? console.log('服务启动失败') : console.log('服务启动成功');
});

控制台报错:
Access to XMLHttpRequest at ‘http://127.0.0.1:2200/’ from origin ‘null’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.


解决

  • jsonp处理

          原理
          利用javascript标签请求不受同源协议影响的原理,
          通过在客户端中创建script标签,在对应src中插入请求路径并携带执行函数的函数名参数到后端
          在后端拼接一个函数执行的字符串,返回前端
          在前端接收并执行
          这样就可以拿到后端的数据了
    
<body>
    <button>发送POSTbutton>

    <script type="text/javascript">
        // 创建用于接收后端参数的方法
        function getHero(data) {
            data.forEach(element => {
                console.log(element.uname);
            });
        };
    script>

    <script>
        // 创建JSONP方法
        function myJsonp({
            url,
            methodName,
        }) {
            // 创建script
            let script = document.createElement('script');
            // 拼接路径,再拼接传递参数(函数名)
            script.setAttribute('src', url + '?callback=' + methodName);
            // 在头部插入script
            document.head.appendChild(script);
            // 使用后移除script标签 避免过多的script标签
            document.head.removeChild(script);
        }

        // 调用jsonp
        // 传入对应路径和方法名
        myJsonp({
            url: 'http://localhost:2200/getHero',
            methodName: 'getHero'
        });
    script>

body>

后端

const http = require('http');

const url = require('url');

const server = http.createServer();

server.on('request', (request, response) => {

    if (request.method === 'GET') {

        let prop = url.parse(request.url, true);

        let obj = [{ uname: 'Tom' }, { uname: 'Boby' }, { uname: 'anla' }];

        response.end(prop.query.callback + '(' + `${JSON.stringify(obj)}` + ');');
        
    } else {
        response.end('post');
    }
});

server.listen(2200, err => {
    err ? console.log('服务启动失败') : console.log('服务启动成功');
});

  • CORS

    1 CORS(跨域资源共享)
    CORS基本思想:使用自定义的HTTP头部让浏览器和服务器通信
    2 简单请求与非简单请求:
    浏览器将CORS请求分成两类:简单请求和非简单请求。只要同时满足以下两大条件,就属于简单请求。

    请求方法是以下三种方法之一:
    HEAD
    GET
    POST
    HTTP的头信息不超出以下几种字段:
    > Accept
    > Accept-Language
    > Content-Language
    > Last-Event-ID
    > Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
    对于简单请求,浏览器直接发出CORS请求。具体来说,就是在头信息之中,增加一个Origin字段。

    非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUT或DELETE,
    或者Content-Type字段的类型是application/json。非简单请求的CORS请求,会在正式通信之前,
    增加一次HTTP查询请求,称为"预检"请求(preflight)。

    CORS字段
    Access-Control-Allow-Origin
    必须。值为允许域名的地址或者是一个*表示允许所有域名地址的请求。
    Access-Control-Allow-Credentials
    可选。一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。
    设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。
    这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。
    Access-Control-Request-Method
    必须,指明允许的CORS请求用到HTTP方法。GET, POST, PUT, PATCH, DELETE ···
    Access-Control-Request-Headers
    该字段可选。该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段。

前端并无太大变化,主要后端设置

const http = require('http');

const server = http.createServer();

server.on('request', (request, response) => {

    // 设置跨域允许的域---只允许来自http://127.0.0.1:5500(挂起静态页面的服务地址,这里是我是用插件挂起的服务)的请求
    response.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:5500');

    // 允许来自所有域的请求
    // response.setHeader('Access-Control-Allow-Origin', '*');

    // 设置允许的请求方法
    response.setHeader('Access-Control-Request-Methods', 'GET', 'post');

    if (request.method.toLocaleLowerCase() === 'get') {
        response.end('get');
    } else {
        response.end('post');
    }
});

server.listen(2200, err => {
    err ? console.log('服务启动失败') : console.log('服务启动成功');
});

  • 设置代理服务器

代理服务器

const http = require('http');

const server = http.createServer();

/* 简单的代理服务器 */

server.on('request', (request, response) => {

    // 请求后立即重定向到新的服务器对应地址

    response.writeHead(302, { 'Location': 'http://127.0.0.1:4400/' });

    // 终止请求
    response.end();

    /* 利用服务器之间的请求不会产生跨域问题的原理 */

});

server.listen(2200, err => {
    err ? console.log('代理服务启动失败') : console.log('代理服务启动成功');
});

资源服务器

const http = require('http');

const server = http.createServer();

/* 目标服务器 */

server.on('request', (request, response) => {

    if (request.method.toLocaleLowerCase() === 'get') {
        response.end('get');
    } else {
        response.end('post');
    }
});

server.listen(4400, err => {
    err ? console.log('服务启动失败') : console.log('服务启动成功');
});

你可能感兴趣的:(Node,websocket,网络,http)