梦相随1006

版权归 梦相随1006 所有,未经 https://www.cnblogs.com/xin1006 作者许可,严禁转载

导航

Access-Control-Allow-Origin 跨域问题 SpringMVC解决 与 前端JS Webpack解决

 

 

 

跨域问题 是针对ajax的一种限制

跨域:浏览器对于JS的同源策略的限制。

以下情况都属于跨域:

域名不同                       如: www.jd.com   www.taobao.com

域名相同,端口不同       如: www.taobao.com:8081  www.taobao.com:8082

二级域名不同               如: 3c.tmall.com   chaoshi.tmall.com 

http和https也属于跨域

 

解决跨域问题的方案

目前比较常用的跨域解决方案有3种:

  • Jsonp

    最早的解决方案,利用script标签可以跨域的原理实现。  限制:需要服务的支持 ;  只能发起GET请求

  • nginx反向代理

    思路是:利用nginx把跨域反向代理为不跨域,支持各种请求方式   缺点:需要在nginx进行额外配置,语义不清晰

  • CORS

    规范化的跨域请求解决方案,安全可靠。

    优势:在服务端进行控制是否允许跨域,可自定义规则 ;   支持各种请求方式

    缺点: 会产生额外的请求

 

*****因为我们将采用CORS的方式解决,故重点介绍一下它如何来处理!!!*****

   

    CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)

它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。

  • 浏览器端:目前,所有浏览器都支持该功能(IE10以下不行)。整个CORS通信过程,都是浏览器自动完成,不需要用户参与

  • 服务端:CORS通信与AJAX没有任何差别,因此你不需要改变以前的业务逻辑。浏览器会在请求中携带一些头信息,我们需要以此判断是否允许其跨域,然后在响应头中加入一些信息即可。这一般通过过滤器完成即可。

 

浏览器会将ajax请求分为两类,其处理方案略有差异:简单请求、特殊请求

简单请求

只要同时满足以下两大条件,就属于简单请求。:

(1) 请求方法是以下三种方法之一:HEAD  GET  POST

(2)HTTP的头信息不超出以下几种字段: Accept  Accept-Language  Content-Language  Last-Event-ID  Content-Type:只限于三个值application/x-www-form-urlencodedmultipart/form-datatext/plain

当浏览器发现发起的ajax请求是简单请求时,会在请求头中携带一个字段:Origin

 

Origin中会指出当前请求属于哪个域(协议+域名+端口)。服务会根据这个值决定是否允许其跨域。

如果服务器允许跨域,需要在返回的响应头中携带下面信息:

Access-Control-Allow-Origin: http://yangw.com
Access-Control-Allow-Credentials: true
Content-Type: text/html; charset=utf-8

 

Access-Control-Allow-Origin:可接受的域,是一个具体域名或者*(代表任意域名)

Access-Control-Allow-Credentials:是否允许携带cookie,默认情况下,cors不会携带cookie,除非这个值是true

要想操作cookie,需要满足3个条件:

      服务的响应头中需要携带Access-Control-Allow-Credentials并且为true。

      浏览器发起ajax需要指定withCredentials 为true

      响应头中的Access-Control-Allow-Origin一定不能为*,必须是指定的域名

 

特殊请求

不符合简单请求的条件,会被浏览器判定为特殊请求,,例如请求方式为PUT

特殊请求会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。

浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。

与简单请求相比,除了Origin以外,多了两个头:

 

Access-Control-Request-Method:  接下来会用到的请求方式,比如PUT

Access-Control-Request-Headers:  会额外用到的头信息

Access-Control-Max-Age:本次许可的有效时长,单位是秒,过期之前的ajax请求就无需再次进行预检了(让它默认,不用处理)

 

我们只要解决了复杂清醒,简单情形自然包含了!

解决方式1:后端JAVA

我们用Java框架SpringMVC实现: 由于我这里是一个Spring Cloud项目,故写了个过滤器放在了网关里面统一处理

 

解决方式2--只在前端webpack-dev-server

webpack配置中主要的参数说明

2.1 ‘/api’
捕获API的标志,如果API中有这个字符串,那么就开始匹配代理,
比如API请求/api/users, 会被代理到请求 http://www.baidu.com/api/users 。

2.2 target
代理的API地址,就是需要跨域的API地址。
地址可以是域名,如:http://www.baidu.com
也可以是IP地址:http://127.0.0.1:3000
如果是域名需要额外添加一个参数changeOrigin: true,否则会代理失败。

2.3 pathRewrite
路径重写,也就是说会修改最终请求的API路径。
比如访问的API路径:/api/users,
设置pathRewrite: {’^/api’ : ‘’},后,
最终代理访问的路径:http://www.baidu.com/users,
这个参数的目的是给代理命名后,在访问时把命名删除掉。

2.4 changeOrigin
这个参数可以让target参数是域名。

2.5 secure
secure: false,不检查安全问题。
设置后,可以接受运行在 HTTPS 上,可以使用无效证书的后端服务器

2.6 其他参数配置查看http-proxy-middleware文档
其他的配置参数等信息,可以查看这里:https://github.com/chimurai/h…

 

*********************以上两种解决方式任选其一均可**************

 

 

 关于环境,我还在hosts中配置了域名映射,使用了nginx帮我反向代理

可以参考我上一篇博文  https://www.cnblogs.com/yangw/p/11947752.html

 

posted on 2019-11-28 23:30  梦相随1006  阅读(1558)  评论(0编辑  收藏  举报