跨域方法汇总

一、跨域的理解

  • 什么是跨域?
    • 一个域下的文档或脚本试图访问另一个域下的资源。
  • ajax发送http请求就会有跨域问题?那为什么在浏览器地址栏输入同样的url没有跨域问题?
    • ajax文件所在的位置是一个域,而服务器的文件相当于一个域,显然你不能从一个域直接拿到另一个域的数据,如果这样,那多不安全。而你在浏览器输入url,只是向服务器里发送请求,把相关的html,js全部加载下来,而这些东西是保存在同一个服务器这个域里面的(后台、前端文件是放在一起的),所以不存在跨域说法了。
  • 为什么会有跨域?
    • 这个是由于浏览器的同源策略。即同协议、同域名、同端口。

二、什么才叫同源?

例如: http://www.baidu.com/index.html的同源检测
  • http://www.baidu.com/dirr/index.html 同源
  • https://www.baidu.com/index.html 不同源 (不同协议)
  • http://www.qq.com/index.html 不同源 (不同域名)
  • http://www.baidu.com:8080/index.html 不同源 (端口不同)
同源策略限制不同源的3种行为:
  1. cookie、IndexDB、localStorage 无法读取
  2. DOM无法读取
  3. AJAX请求不能发送

三、项目当中遇到的跨域解决方法

1,jsonp

  实现原理:通过script标签不受同源策略的限制,在本站点动态创建一个script标签,指定src属性为跨域的地址,并且提供一个回调函数来接受返回的数据,第三方产生的数据是一个json数据的包装,比如:onBack({'params':11}),然后再调用本站点的回调函数。这样就拿到了不同源的数据。
//前端代码实现

let script = document.createElement('div') 
script.type = 'text/javascript' 
script.src = 'http://192.168.0.0:8080?user=shao&callback=onBack' 
function onBack(res){ console.log(JSON.stringify(res)) } //后端代码实现 onBack({'status':true,user:'admin'})

jsonp的缺点是:只能实现get方式请求。

2,CORS
  CORS是W3C标准,允许浏览器跨域发送AJAX请求,需要浏览器和服务器同时支持。CROS通信过程中,如果AJAX跨域请求,则会自动添加一些附件的请求头信息,有时还会多一次附加请求,但用户是无感知的。CORS支持所有类型的HTTP请求。
服务端设置Access-Control-Allow-Origin
let xhr = new XMLHttpRequest(); 
xhr.withCredentials = true; //前端设置是否携带cookie 

//后端代码实现 
// 允许跨域访问的域名:若有端口需写全(协议+域名+端口),若没有端口末尾不用加'/' 
response.setHeader("Access-Control-Allow-Origin", "http://www.domain1.com"); 

// 允许前端带认证cookie:启用此项后,上面的域名不能为'*',必须指定具体的域名,否则浏览器会提示 
response.setHeader("Access-Control-Allow-Credentials", "true"); 

// 提示OPTIONS预检时,后端需要设置的两个常用自定义头 
response.setHeader("Access-Control-Allow-Headers", "Content-Type,X-Requested-With");
 
3,使用nginx服务代理
  由于项目中需要调用众多不同源的接口,前端需要处理不同环境不同源的接口地址切换,所以统一使用nginx代理转发,前端只需要处理当前源下的请求,跨域代理的配置主要在nginx的http配置项。
  假设服务器域名为example.com,需要跨域请求example.com:8099的短信服务和example2.com下的网关服务,那么我们在本站点上配置/message下的请求转发到example.com:8099服务器上,配置/gateway转发到example2.com的服务器上。
http {   # 虚拟主机配置   
    server {    
    #监听80端口        
    listen       80;      
    #使用example.com 访问         
    server_name  example.com;         
    #开启gzip压缩         
    gzip  on;         
    gzip_disable "MSIE [1-6].";         
    #默认请求        
    location / {             
        root   html;             
        index  index.html index.htm;         
    } 
    # 将http://example.com/message/下的请求转发到http://example.com:8099/message/        
     location /message/ { 
        proxy_pass http://example.com:8099/message/         
    } 
    # 将http://example.com/gateway/下的请求转发到http://example2.com/gateway/         
    location /gateway/ { 
    proxy_pass http://example2.com/gateway/         
    } 
   }
}
 4,webpack跨域配置
... 
dev:{ 
    ... proxyTable: {
     '/project-manage': { 
        target: 'http://192.168.2.67:7999/', 
        changeOrigin: true, //是否跨域 
        pathRewrite: { 
            '^/project-manage': '' 
            } 
        } 
    }, 
}
             
 
总结:除了上面列举的跨域方法外,还有postMessage,window.name等。
 

猜你喜欢

转载自www.cnblogs.com/shaofl/p/10504961.html