前端跨域问题解决方案汇总

下面我以简单的两台node服务器来讲明如何使用nginx进行前端跨域访问。html

  1. node1服务器 在localhost:8083上启动
const app = express();
app.get('/web/users',(req, res)=>{
    res.json([{name:"张三",age:12},{name:"李四",age:14}]);
    res.end()
})
app.listen(process.env.PORT || 8083);
复制代码

同域下的前端代码只需调用前端

function getUsers() {
        var xhr=new XMLHttpRequest();
        xhr.open('GET', 'http://localhost:8083/web/users');
        xhr.send(null);
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4 && xhr.status == 200) {
              alert(xhr.responseText);
            }else {
              alert(xhr.statusText);
            }
        }
}
复制代码

这里有一点须要关注的是,先后端代码处在同一个域下,xhr.open() url路径写成下面这样也是能够的,它会默认请求到http://localhost:8083/web/usersnode

xhr.open('GET', '/web/users');
复制代码

下面咱们将node1服务器中的web/users接口删除:nginx

const app = express();
app.listen(process.env.PORT || 8083);
复制代码

前端此时天然没法访问后台的web/users了,将报一个404错误。web

下面增长一个node2服务器,在localhost:8085上启动,同时咱们将原先在8083上删除的web/users接口搬迁到8085上:ajax

const app = express();
app.get('/web/users',(req, res)=>{
    res.json([{name:"张三",age:12},{name:"李四",age:14}]);
    res.end()
})
app.listen(process.env.PORT || 8085);
复制代码

因为8085实现了这个接口,咱们尝试在原先8083端口下的ajax调用它试试:express

xhr.open('GET', 'http://localhost:8085/web/users');
复制代码

如咱们所料,浏览器阻止了这次行为,并抛出一个跨域错误。 npm

难道就没法访问那个接口了吗?其实服务器之间和服务器之间是能够相互调用的,阻止跨域访问只是在浏览器端作的限制而已。json

下面我经过两种方式来实现如何访问到8085上的web/users接口。后端

1 . node直接做为代理访问

原理就是交由8083后端去访问8085端口接口,访问完成交给前端
8083node后端实现代码:

npm install request --save // 须要安装一个http request模块
复制代码
const app = express()
const request = require('request')
// 访问此接口时经过request模块去访问8085 再返回给前端。
app.get('/web/users',(req, res)=>{
    var url='http://localhost:8085'+req.url
    console.log(url) // http://localhost:8085/web/users
    req.pipe(request(url)).pipe(res);
})
复制代码

2. jsonp方式访问

就是经过script 的src,向服务器请求数据,且这不受同源策略限制;而后服务器将相应的数据放入指定的函数回调名中,返回给前端。说的有点绕,下面经过实例讲解: 8083前端请求8085,这里已经再也不是ajax请求了,而是直接加载8085上资源。

<script>
       function getUsers(data) {
         alert(data)
       }
    </script>
    <script src="http://localhost:8085/jsonp?callback=getUsers"></script>
复制代码

上述代码第一个script标签订义了一个函数getUsers 可是并无执行,只是定义了而已,要想有执行能力,须要

getUsers(data) 
复制代码

因此咱们要让第二个标签script src="http://localhost:8085/jsonp?callback=getUsers" 返回getUsers(data)内容便可,这样第一个标签内定义的函数就能够执行了。返回接口内容只须要放到函数参数里便可
后台8085实现:

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

// 处理前端jsonp请求
app.get('/jsonp',(req,res)=>{
  var qs = querystring.parse(req.url.split('?')[1]); //{callback:'getUsers'}
  var users=JSON.stringify([{name:"张三",age:12},{name:"李四",age:14}]) // 注意须要传成字符串格式
  var callback=`${qs.callback}(${users})`
  res.end(callback)
})
复制代码

前端返回

是否是有点黑魔法的味道!可是缺点也是明显的,首先经过此方式有必定安全性的,经过callback后加一些乱七八糟的东西可能会有xss攻击,最主要的是jsonp不支持post方法。

3 .nginx反向代理器

此方式即相似于第一种node代理方式,也是经过服务器和服务器之间通讯,只是不须要8083下后台服务器本身去访问8085,而是专门交给nginx,为何?姑且认为nginx更加专业吧! nginx配置

server {
        listen 8007;          # nginx启动端口,须要访问这个端口才可以代理
        server_name localhost:8083; # 须要代理的服务器
        location / {          # 若是你访问127.0.0.1/8002/的话nginx去请求
          proxy_pass http://localhost:8083;
        }
        location /web { #访问/web/aa时会映射成http://localhost:8085/web/aa;
          proxy_pass   http://localhost:8085;
        }
    }
复制代码

8083请求路径

xhr.open('GET', '/web/users');
复制代码

3 CORS

CORS全称是跨域资源共享 是一个W3C标准,它规定浏览器容许发送ajax到不一样域下的服务器来获取数据,从而克服了原来限制,使用CORS须要先后端都支持,现代浏览器基本上都支持。具体CORS的知识能够参考阮一峰博客 www.ruanyifeng.com/blog/2016/0…

app.use('*',function (req, res, next) {
  res.header('Access-Control-Allow-Origin', '*'); //这个表示任意域名均可以访问,这样写不能携带cookie了。
//res.header('Access-Control-Allow-Origin', 'http://www.baidu.com'); //这样写,只有www.baidu.com 能够访问。
  res.header('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild');
  res.header('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');//设置方法
  if (req.method == 'OPTIONS') {
    res.send(200); 
  }
  else {
    next();
  }
});
复制代码

或者使用现成的CORS模块

npm install cors
复制代码
var express = require('express')
var cors = require('cors')
var app = express()

var corsOptions = {
  origin: 'http://www.baidu.com',
  optionsSuccessStatus: 200 
}

app.get('/products/:id', cors(corsOptions), function (req, res, next) {
  res.json({msg: '只有百度能够访问'})
})

app.listen(80, function () {
  console.log('CORS-enabled web server listening on port 80')
})
复制代码

若有不正确,请指正^_^

相关文章
相关标签/搜索