Node服务端解决跨域问题

Cors解决跨域

在解决跨域问题之前我们先来看一看以下几个问题:

一、为什么会出现跨域

出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)

二、什么是跨域

当一个请求的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域

当前页面url被请求页面url是否跨域原因
http://www.test.com/http://www.test.com/index.html同源(协议、域名、端口号相同)
http://www.test.com/https://www.test.com/index.html跨域协议不同
http://www.test.com/http://www.baidu.com/跨域主域名不同
http://www.test.com/http://blog.test.com/跨域子域名不同
http://www.test.com/http://www.test.com:8080/跨域端口号不同

三、非同源限制

  • 无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB
  • 无法接触非同源网页的 DOM
  • 无法向非同源地址发送 AJAX 请求

四、解决办法

1、CORS

CORS 是跨域资源分享(Cross-Origin Resource Sharing)的缩写。它是 W3C 标准,属于跨源 AJAX 请求的根本解决方法。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。

浏览器将CORS跨域请求分为简单请求和非简单请求

简单请求:(需同时满足以下两点)
                1.请求的方式只能是GET,POST,HEAD
                2.HTTP请求头是:
                    Accept
                    Accept-Language
                    Content-Language
                    Content-Type: 只限于三个值:application/x-www-form-urlencoded、multipart/form-data、text/plain
不同时满足上面的两个条件,就属于非简单请求。浏览器对这两种的处理,是不一样的。

非简单请求:(满足任意一点)
                1.请求方式为除GET,POST,HEAD之外的Method类型
                2.请求头包含自定义头端
                3.向服务器发送了application/json格式的数据  
   非简单请求在请求CROS时,会在正式通信之前,增加一次HTTP查询请求,称为预检请求。
简单、非简单请求的区别:简单请求之发送一次请求,预检请求发送两次请求,在发送之前会先发送一次OPTION的与请求,与请求成功之后才会发送实际的请求和数据 
1.CORS主要是在服务端进行配置,客户端浏览器无需做任何配置,即可请求开启了CORS的接口

2.CORS在浏览器中有兼容性

3.CORS默认情况下只支持GET、POST、HEAD,如果客户端希望通过PUT\DELETE等方式请求服务器资源,则须通过Access-Control-Allow-Methods来指明实际请求所允许的HTTP方法
res.setHEader('Access-Control-Allow- Methods','POST,GET,DELETE,HEAD')
或者
res.setHEader('Access-Control-Allow-Methods',*)
前端解决
  1. 原生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);
        }
    };
    
  2. jQuery Ajax

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

    a.) axios设置:

    axios.defaults.withCredentials = true
    

    b.) vue-resource设置:

    Vue.http.options.credentials = true
    
服务端解决
  1. Nodejs(Express,前端无需设置任何东西即可解决)

    /*
    CORS(主流方案):cors是express提供的第三方库,通过安装和配置cors中间件,可以很方便的解决跨域问题
                由一系列HTTP的响应头组成,这些HTTP响应头决定浏览器是否阻止前端JS代码跨域获取资源
    步骤:
    	1.安装: npm i cors
        2.导入中间件 const cors = require("cors")
    	3. 配置中间件 app.use("cors()")
    */
    const express = require('express');
    const app = express();
    // 配置cros跨域请求中间件
    const cors = require('cors')
    app.use(cors())
    
    const api = require('./api')
    app.get('/api/jsonp',(req,res)=>{
        const fuName = req.query.callback;
        const data = {name:'黎明'};
        let str =  `${fuName}(${JSON.stringify(data)})`
        res.send(str)
    }) 
    app.use(express.urlencoded({extended:false}))
    app.use('/api',api)
    app.use((err,req,res,next)=>{
        res.send('Error'+err.message)
    })
    app.listen(80,()=>{
        console.log('http://localhost');
    })
    
    原生Node(需和前端一起使用)
    var http = require('http');
    var server = http.createServer();
    var qs = require('querystring');
     
    server.on('request', function(req, res) {
        var postData = '';
     
        // 数据块接收中
        req.addListener('data', function(chunk) {
            postData += chunk;
        });
     
        // 数据接收完毕
        req.addListener('end', function() {
            postData = qs.parse(postData);
     
            // 跨域后台设置
            res.writeHead(200, {
                'Access-Control-Allow-Credentials': 'true',     // 后端允许发送Cookie
                'Access-Control-Allow-Origin': 'http://www.domain1.com',    // 允许访问的域(协议+域名+端口)
                /* 
                 * 此处设置的cookie还是domain2的而非domain1,因为后端也不能跨域写cookie(nginx反向代理可以实现),
                 * 但只要domain2中写入一次cookie认证,后面的跨域接口都能从domain2中获取cookie,从而实现所有的接口都能跨域访问
                 */
                'Set-Cookie': 'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly'  // HttpOnly的作用是让js无法读取cookie
            });
     
            res.write(JSON.stringify(postData));
            res.end();
        });
    });
     
    server.listen('8080');
    console.log('Server is running at port 8080...');
    

跨域解决参考链接

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值