三种解决跨域问题的方法

跨域问题

通过xhr进行ajax通信的一个主要限制是同源(同协议、同域名、同端口)策略。默认情况下,xhr只能访问与发起请求的页面在同一个域内的资源。这个安全策略可以防止某些恶意行为。

解决跨域的三种方法

我们在5000端口开启一个服务,需要做的是跨域请求服务端返回的数据。

sever1.js如下

const express=require('express');

const app=express();

app.use((request,response,next)=>{
    
    
    console.log('有人请求server1啦!');
    next();
});

app.get('/student',(request,response)=>{
    
    
    const data={
    
    
        'name':"amethyst",
        "color":"blueviolet"
    }

    response.send(JSON.stringify(data));
});

app.listen(5000,()=>{
    
    
    console.log('5000端口监听中...');
});

1、跨源资源共享(CORS)

CORS(Cross-Origin Resource Sharing)定义了浏览器与服务器如何实现跨源通信,其背后的思路就是使用自定义的HTTP头部允许浏览器和服务器相互了解,以确定请求或响应应该是成功还是失败。

这种方法我们只需要在服务端设置请求头即可
server1.js

app.get('/student',(request,response)=>{
    
    
    response.setHeader('Access-Control-Allow-Origin','*');
    const data={
    
    
        'name':"amethyst",
        "color":"blueviolet"
    }
    response.send(JSON.stringify(data));
});

客户端可以直接请求5000端口的数据:

axios.get('http://localhost:5000/student').then((res)=>{
    
    
    var pObj=document.createElement('p');
    var con=res.data;
    pObj.innerHTML=`
        <h3>name: ${
      
      con.name}</h3>
        <h3>color: ${
      
      con.color}</h3>
    `;
    document.body.appendChild(pObj);
}).catch(()=>alert('error'));

在这里插入图片描述

2、JSONP

jsonp利用了script标签不受同源策略限制的特点,通过动态创建script标签,并为src属性指定跨域url来实现的

jsonp看起来和json一样,只是会被包在一个函数回调里面,如:

callback({
    
    "name":"lanlan"})

jsonp格式包含两个部分:回调和数据。回调是在页面接收到响应之后应该调用的函数,通常回调函数的名称是通过请求来动态指定的,而数据就是作为参数传给回调函数的json数据

jsonp服务通常支持以查询字符串形式指定回调函数的名称,比如以下整改例子的回调函数名称就被指定为handleResponse

客户端

var handleResponse=function(res){
    
    
    console.log(res);
}
var script=document.createElement('script');
script.src='http://localhost:5000/student?callback=handleResponse';
document.body.insertBefore(script,document.body.firstChild);

服务端

app.get('/student',(request,response)=>{
    
    
    const data={
    
    
        'name':"amethyst",
        "color":"blueviolet"
    }
    var str=JSON.stringify(data);
    var cb=request.query.callback;
    response.send(`${
      
      cb}(${
      
      str})`);
});

在这里插入图片描述

3、react脚手架配置代理(proxy)

我们的react项目在3000端口启动,现在仍然是要请求5000端口的数据。

产生跨域问题的本质是ajax引擎把从5000端口的响应体拦住了,而代理的作用就相当于一个中间人,转发ajax请求。由于代理服务器没有ajax引擎,并且是开在3000端口下的,因此可以接收从5000端口返回的数据并返回给3000端口,这样便解决了跨域问题。
在这里插入图片描述

第一种配置代理的方法

直接在package.json文件下配置proxy:

"proxy":"http://localhost:5000"

这样的话,客户端就直接向3000端口发送请求,如果请求的数据在3000端口,就直接返回响应体,否则代理服务器会再将请求转发给5000端口

handleClick(){
    
    
   axios.get('http://localhost:3000/student').then((res)=>{
    
    
       var pObj=document.createElement('p');
       var con=res.data;
       pObj.innerHTML=`
           <h3>name: ${
      
      con.name}</h3>
           <h3>color: ${
      
      con.color}</h3>
       `;
       document.body.appendChild(pObj);
   }).catch(()=>alert('error'));
}

在这里插入图片描述

第二种配置代理的方式

新建一个setupProxy.js文件,在里面配置proxy,这种方法可以同时设置转发多个请求

const proxy=require('http-proxy-middleware');

module.exports=function(app){
    
    
    app.use(
        proxy('/api1',{
    
    
            target:'http://localhost:5000',
            changeOrigin:true,
            pathRewrite:{
    
    '^/api1':''}
        }),
        proxy('/api2',{
    
    
            target:'http://localhost:5001',
            changeOrigin:true,
            pathRewrite:{
    
    '^/api2':''}
        })
    );
}

遇见api1、api2就会触发该代理配置

target决定转发给谁

changeOrigin默认是false,控制服务器请求头中Host的值,当其值为true时,服务器收到的请求头中Host的值就是转发的目的端口,但是实际上来自于其他端口,这样就完美地欺骗了服务器,让其以为是自己端口下发出的请求

加入api2只是为了匹配端口发送代理,但是目的端口下是没有api2的,如第一个ajax请求,如果不通过pathRewrite将/api2替换成空字符串的话,代理将会转发请求到http://localhost:5000/api2/car,但是5001端口下并没有api2,这样就会报错。api1也是同理

axios.get('http://localhost:3000/api1/student').then((res)=>{
    
    
   var pObj=document.createElement('p');
   var con=res.data;
   pObj.innerHTML=`
       <h3>name: ${
      
      con.name}</h3>
       <h3>color: ${
      
      con.color}</h3>
   `;
   document.body.appendChild(pObj);
}).catch(()=>alert('error'));

axios.get('http://localhost:3000/api2/car').then((res)=>{
    
    
   var pObj=document.createElement('p');
   var con=res.data;
   pObj.innerHTML=`
       <h3>name: ${
      
      con.name}</h3>
       <h3>color: ${
      
      con.color}</h3>
   `;
   document.body.appendChild(pObj);
}).catch(()=>alert('error'));

请求地址

const {
    
     response } = require('express');
const express=require('express');

const app=express();

app.use((request,response,next)=>{
    
    
    console.log('有人请求服务器2啦!');
    console.log('请求来自于',request.get('Host'));
    console.log('请求的地址',request.url);
    next();
})

app.get('/car',(request,response)=>{
    
    
    const data={
    
    
        "name":"lanlan",
        "color":"pink"
    }

    response.send(JSON.stringify(data));
})

app.listen(5001,()=>{
    
    
    console.log('5001端口监听中...');
})

在这里插入图片描述

这样便解决了跨域问题,同时也可以对多个端口发送请求~
在这里插入图片描述

おすすめ

転載: blog.csdn.net/Amethystlry/article/details/114663640