跨域的理解与解决方法

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

跨域资源共享(CORS)是一种机制,它使用额外的http头告诉浏览器让运行在一个origin上的web应用被准许访问来自不同资源服务器上的指定资源

CORS不是一种错误,而是为了保护用户的一种安全机制

为什么会出现跨域问题?

XmlHttpRequest同源策略:禁止不同源的AJAX请求,主要防止CSRF攻击

CORS 请求失败会产生错误,但是为了安全,在 JavaScript 代码层面无法获知到底具体是哪里出了问题。你只能查看浏览器的控制台以得知具体是哪里出现了错误。

同源策略:

是浏览器的一种核心最基本的安全策略。他对来自于不同源的文档或脚本对当前文档的读写做出了限制。

同源即协议相同、域名相同、端口相同

与跨域有关的协议头

Access-Contorl-Allow-Origin

Access-Control-Allow-Origin: <origin> | *

Access-Control-Allow-Origin 参数指定了单一的源,告诉浏览器允许该源访问资源。或者,对于不需要携带身份凭证的请求,服务器可以指定该字段的值为通配符“*”,表示允许来自任意源的请求。

例如,为了允许来自 https://mozilla.org 的代码访问资源,你可以指定:

Access-Control-Allow-Origin: https://mozilla.org
Vary: Origin

如果服务端指定了具体的单个源(作为允许列表的一部分,可能会根据请求的来源而动态改变)而非通配符“*”,那么响应标头中的 Vary字段的值必须包含 Origin。这将告诉客户端:服务器对不同的 Origin返回不同的内容。

Access-Control-Expose-Header

在跨源访问时,XMLHttpRequest 对象的 getResponseHeader() 方法只能拿到一些最基本的响应头,Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma,如果要访问其他头,则需要服务器设置本响应头。

该头将指定标头放入允许列表中,供浏览器的 JavaScript 代码(如 getResponseHeader())获取。

Access-Control-Expose-Headers: <header-name>[, <header-name>]*

具体用法在:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS#http_%E5%93%8D%E5%BA%94%E6%A0%87%E5%A4%B4%E5%AD%97%E6%AE%B5

 解决方法:

通过jsonp解决跨域

原生使用方法:

​
1.yarn add jsonp --save
 
2.import JsonP from 'jsonp'
 
3.JsonP('url',{},function(err, data){
 
  console.log(data)
 
})

​

要是在react中使用可以先进行封装在使用

import JsonP from 'jsonp'
export default class Axios {
    static jsonp(options){
        return new Promise((resolve,reject)=>{
            JsonP(options.url,{
                param:'callback'
            },function(err,res){
                if(res.status === 'success') {
                    resolve(res)
                } else {
                    reject(err)
                }
            })
        })
    }
}

引用:

import Axios from '../../axios/index'  // 封装的文件路径
Axios.jsonp({url:'path'}).then((res)=>{
    console.log(res)
}).catch((err)=>{
    console.log(err)
})    

用于安全请求的CORS

如果一个请求是跨域的,浏览器始终会向其添加 Origin header。

例如,如果我们从 https://javascript.info/page 请求 https://anywhere.com/request,请求的 header 将如下所示:

GET /request
Host: anywhere.com
Origin: https://javascript.info

正如你所看到的,Origin 包含了确切的源(domain/protocol/port),没有路径(path)。

服务器可以检查 Origin,如果同意接受这样的请求,就会在响应中添加一个特殊的 header Access-Control-Allow-Origin。该 header 包含了允许的源(在我们的示例中是 https://javascript.info),或者一个星号 *。然后响应成功,否则报错。

浏览器在这里扮演受被信任的中间人的角色:

  1. 它确保发送的跨源请求带有正确的 Origin
  2. 它检查响应中的许可 Access-Control-Allow-Origin,如果存在,则允许 JavaScript 访问响应,否则将失败并报错。

这是一个带有服务器许可的响应示例:

200 OK
Content-Type:text/html; charset=UTF-8
Access-Control-Allow-Origin: https://javascript.info

服务端代理(Nginx代理)

#如果监听到请求接口地址是 www.xxx.com/api/page ,nginx就向http://www.yyy.com:9999/api/page这个地址发送请求
server {
     listen       80; 
        server_name  www.xxx.com;
        #判过滤出含有api的请求
        location /api/ { 
            proxy_pass http://www.yyy.com:9999; #真实服务器的地址
        }
}

前端解决方法:

在react中可以在package.json中添加

假设请求地址为:http://xxxx/api/data

"proxy":"http://xxxx"

然后在axios中更改请求地址:

/api/data

最后就可以重启项目,测试是否解决跨域

  • 8
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值