首页 > 编程知识 正文

跨域的常见解决方法,解决跨域的方法

时间:2023-05-04 04:54:31 阅读:264329 作者:3827

其他跨域方案请看:

1、JSONP跨域方案

 

以下介绍CORS跨域解决方案

一、什么是CORS?

CORS (Corss-Orign Resource Sharing) 是W3C工作草案,是一份浏览器技术的规范。定义了跨域资源访问时,浏览器和服务器之间如何通信,使用自定义的http头部允许浏览器和服务器相互了解对方,从而决定请求或响应成功与否。CORS在现代浏览器都支持,使用和普通的ajax没有任何区别,关键是只要服务器实现CORS接口。

 

二、如何使用

现代浏览器都支持CORS,所以前端不需要做任何改变,即使普通的ajax,只需要服务器实现CORS接口;http如何请求服务器,我们不会有如何感觉。

 

三、服务端处理流程

 

HTTP请求

1、查看http头部是否有Origin,没有直接结束,有到第2步。

2、查看Origin是否有效,无效则返回403,有效则第3步。

3、查看method是否有效,无效则返回403,是有效则第4步。

4、查看是否是OPTION请求,不是则简单请求处理,是则预检处理。

 

简单请求处理:

返回Allow-Origin, Allow-Credentials等,并返回正常内容

 

预检处理:

返回Allow-Origin, Allow-Credentials等,内容为空,只有当浏览器下一次发出实际http请求才返回内容

 

四、客户端处理机制

浏览器将CORS请求分成两类:简单请求和预检请求(非简单请求),不需要做其他设置

划分的依据为:

(1) 简单请求(需要同时满足下面两个条件)

         请求方法是:HEAD ,GET,POST 三者之一

         HTTP头信息不超过以下字段:Accept,Accept-Language,Content-Language,Last-Event-ID,Content-Type(只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain)

 

        简单请求时,浏览器会直接发起一个跨域请求,并在请求头中携带上Origin,用来说明本次请求来自哪个源。服务器端接受到请求后,根据头信息来判断是否允许跨域,返回一个正常的HTTP响应(如果允许,则响应头携带Access-Control-Allow-Origin等字段,并返回正常内容)。浏览器根据返回的响应头是否携带Access-Control-Allow-Origin等字段判断请求是否请求成功,没有则抛出异常。注意:请求是否成功不能通过状态码来确定,因为有可能也是200,但是请求拒绝了。

    

       异常:

       正确:

(2) 非简单请求

只要不能同时满足简单请求中任意一个条件的就是非简单请求,如果预检成功,浏览器实际一共会发送两次请求。

分别:

option请求

预检成功则发送正常的post请求

 

五、服务器端配置

服务器端可以在多个地方设置,比如ngnix、oss、cdn、web服务器等

主要涉及到的是:

NameRequiredCommentsAccess-Control-Allow-Origin必填允许请求的域,比如:http://www.baidu.com或者所有都允许*Access-Control-Allow-Methods必填允许请求的方法,比如:get、post、put、delete,多个用逗号分割,或者允许所有*Access-Control-Allow-Headers可选预检请求后,告知发送请求需要有的头部Access-Control-Expose-Headers可选

CORS请求时,xmlhttprequest默认只能拿到6个基本字段:Cache-Control、

Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿

到其他字段,就必须在Access-Control-Expose-Headers里面指定。

Access-Control-Max-Age可选本次预检的有效期,单位:秒;在有效期内不需要发出另一条预检Access-Control-Allow-Credentials可选

表示是否允许发送cookie,默认false;比如put或delete,浊者content-type为

application/json等的有特殊要求,需要设置为true

 

1、web服务器

可以通过添加过滤器,或拦截器等处理

<filter><display-name>CORSFilter</display-name><filter-name>CORSFilter</filter-name><filter-class>com.learn.mybatis.controller.filter.CORSFilter</filter-class></filter><filter-mapping><filter-name>CORSFilter</filter-name><url-pattern>/home</url-pattern></filter-mapping> public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletResponse response2 = (HttpServletResponse) response; response2.setHeader("Access-Control-Allow-Origin", "*"); response2.setHeader("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE"); response2.setHeader("Access-Control-Allow-Headers", "Content-Type,Authorization"); response2.setHeader("Access-Control-Max-Age", "10"); chain.doFilter(request, response2);}

 

2、ngnix

来源:https://michielkalkman.com/snippets/nginx-cors-open-configuration/

location / { if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' '*'; # # Om nom nom cookies # add_header 'Access-Control-Allow-Credentials' 'true'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; # # Custom headers and headers various browsers **should** be OK with but aren't # add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type'; # # Tell client that this pre-flight info is valid for 20 days # add_header 'Access-Control-Max-Age' 1728000; add_header 'Content-Type' 'text/plain charset=UTF-8'; add_header 'Content-Length' 0; return 204; } if ($request_method = 'POST') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Credentials' 'true'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type'; } if ($request_method = 'GET') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Credentials' 'true'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type'; }}

 

3、oss

比如阿里云中,

进入OSS管理控制台界面。在左侧存储空间列表中,单击目标存储空间名称,打开该存储空间概览页面。单击基础设置页签,找到跨域设置区域,然后单击设置。

 

4、cdn

 

 

六、带认证的请求

CORS默认情况下是不需要提供cookie,http认证,ssl等的,如果需要携带认证,则需要设置

xmlhttprequest.withCredentials = true;

服务器端需要设置:

Access-Control-Allow-Credentials为true。

不然会报错:

当服务器设置带认证,则Access-Control-Allow-Origin不能设置为*,必须为一个具体的域名。

不然也会报错:

设置正确后,将携带上cookie:

 

七、错误处理

因为CORS错误,浏览器有可能返回的也是200,所以通过状态码无法判定是否出错。

可以使用onerror监听错误,使用onload检测成功

xhr.onerror = function(){ conlose.log("cors error");}

 

八、弊端、缺陷

1、只要服务器Access-Control-Allow-Origin不要设置成*,同时做好认证,在安全性上是比较可靠的,但是在低版本浏览器上并不支持,只能使用jsonp。

2、这点比较重要,CORS的两种请求方式:简单请求和非简单请求;即第一种是先发起请求,然后拦截返回数据;第二种是先请求验证进行拦截,再发起请求。

     所以对于简单请求来讲,即使返回数据被拦截,但是实际走过了后台的整个逻辑,即更新数据库的更新数据库等,但是到浏览器端却通过onerror报请求失败。

 

九、JSONP和CORS比较 NameCompareUsage安全性

因为JSONP不是规范,所以存在很明显的安全漏洞,比如callback注入等。

但是安全没有绝对性,CORS也同样存在漏洞。CORS简单请求失败也会更新数据,这个漏洞在简单请求中存在。

 兼容性JSONP兼容型很强,CORS只支持现在浏览器,低版本ie等不支持低版本使用JSONP,现在浏览器推荐CORS请求方式JSONP只能使用GET,CORS支持所有的http请求有增删改查,推荐使用CORS错误处理JSONP错误处理不完善,CORS可以监听onerror,并通过浏览器控制台查看 复杂度JSONP发送一次get请求,CORS非简单请求会发送两次,第一次预检 

参考:

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS

 

 

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。