跨域访问问题

跨域访问

在日常开发中,尤其是在微服务架构下,不同的微服务部署在不同的端口上,不同端口之间的请求跳转有可能会遇到CORS问题,即:No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

这是浏览器为了保证安全提供安全策略:

  • 规定只有同源的网页才能共享Cookie
  • 规定AJAX请求只能发给同源的网址,否则就报错

如果违反了以上规定,浏览器将会拦截跨域请求,抛出:**No ‘Access-Control-Allow-Origin’ header is present on the requested resource.**等提示。

解析我们从同源策略开始熟悉跨域访问以及跨域问题的解决。

1. 跨域问题由来

1.1 同源策略

1、同源策略简介

浏览器安全的基石是"同源政策"(same-origin policy)。

1995年,同源政策由 Netscape 公司引入浏览器。目前,所有浏览器都实行这个政策。

最初,它的含义是指,A网页设置的 Cookie,B网页不能打开,除非这两个网页"同源"。所谓"同源"指的是"三个相同"。

  • 协议相同

  • 域名相同

  • 端口相同

举例来说,http://www.example.com/dir/page.html这个网址,协议是http://,域名是www.example.com,端口是80(默认端口可以省略)。它的同源情况如下。

http://www.example.com/dir2/other.html:同源
http://example.com/dir/other.html:不同源(域名不同)
http://v2.www.example.com/dir/other.html:不同源(域名不同)
http://www.example.com:81/dir/other.html:不同源(端口不同)

2、同源策略目的

同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。

设想这样一种情况:A网站是一家银行,用户登录以后,又去浏览其他网站。如果其他网站可以读取A网站的 Cookie,会发生什么?

很显然,如果 Cookie 包含隐私(比如存款总额),这些信息就会泄漏。更可怕的是,Cookie 往往用来保存用户的登录状态,如果用户没有退出登录,其他网站就可以冒充用户,为所欲为。因为浏览器同时还规定,提交表单不受同源政策的限制。

由此可见,"同源政策"是必需的,否则 Cookie 可以共享,互联网就毫无安全可言了。

随着互联网的发展,"同源政策"越来越严格。目前,如果非同源,共有三种行为受到限制。

(1) Cookie、LocalStorage 和 IndexDB 无法读取。

(2) DOM 无法获得。

(3) AJAX 请求不能发送。

3、跨域问题

虽然同源策略是必要的,但有时候合法的用途也会受到限制,这时我们可以通过三种方式进行规避:JSONP、WebSocket、CORS

而作为后台开发,我们最常用的便是使用CORS。

1.2 CORS

1、CORS简介

CORS是跨源资源分享(Cross-Origin Resource Sharing)的缩写。它是W3C标准,是跨源AJAX请求的根本解决方法。

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

CORS需要浏览器和服务器同时支持。

整个CORS通信过程,都是浏览器自动完成,不需要用户参与。

对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。

2、CORS执行流程

CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。

我们暂且不谈,主要了解非简单请求

非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUTDELETE,或者Content-Type字段的类型是application/json

image-20201205150915243

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

2、服务器收到"预检"请求以后,检查了OriginAccess-Control-Request-MethodAccess-Control-Request-Headers字段以后,确认允许跨源请求,就可以做出回应。

3、一旦服务器通过了"预检"请求,以后每次浏览器正常的CORS请求,就都跟简单请求一样,会有一个Origin头信息字段。服务器的回应,也都会有一个Access-Control-Allow-Origin头信息字段。

2.解决跨域问题

1.2CORS我们知道:浏览器遇到跨域的AJAX请求时,先发一个预检请求询问服务器,当前网页所在的域名是否在服务器的许可名单之中,而作为服务器端的我们就收到预检请求之后,进行检查,如果符合就需要响应肯定回复。之后每次浏览器正常的CORS请求和普通请求一样。

1、浏览器端的预检请求

OPTIONS /cors HTTP/1.1							# 预检请求用的方法是OPTIONS
Origin: http://api.bob.com						# 表示请求来自那个源
Access-Control-Request-Method: PUT				# 浏览器的CORS请求会用到哪些HTTP方法
Access-Control-Request-Headers: X-Custom-Header # 指定浏览器CORS请求会额外发送的头信息字段
Host: api.alice.com			
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...

2、服务端对浏览器的预检请求的肯定响应

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://api.bob.com # 表示该网址可以请求数据,*表示允许跨源请求
Access-Control-Allow-Methods: GET, POST, PUT	# 表明服务器支持的所有跨域请求的方法
Access-Control-Allow-Headers: X-Custom-Header   # 表明服务器支持的所有头信息字段 
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain

3、浏览器正常请求

PUT /cors HTTP/1.1
Origin: http://api.bob.com						# 浏览器自动添加
Host: api.alice.com
X-Custom-Header: value
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...

4、服务器正常恢复

Access-Control-Allow-Origin: http://api.bob.com	# 每次回应都必定包含的
Content-Type: text/html; charset=utf-8

1.1 SpringCloud环境下解决同源问题

从上面可以知道,作为服务器端,我们需要判断Origin: http://api.bob.comAccess-Control-Request-Method等判断该请求是否合法跨源请求,如果合法即响应Access-Control-Allow-OriginAccess-Control-Allow-Methods等来确认。

在微服务中,我们在网关对请求进行拦截,过滤出跨域请求,并允许所有跨域请求:

@Configuration
public class ApplicationCorsConfig {

    @Bean
    public CorsWebFilter corsWebFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        // 允许所有的请求头
        corsConfiguration.addAllowedHeader("*");
        // 允许所有方法跨域
        corsConfiguration.addAllowedMethod("*");
        // 运行所有源请求跨域
        corsConfiguration.addAllowedOrigin("*");
        // 跨域请求默认不包含Cookie,设置为true可以包含Cookie
        corsConfiguration.setAllowCredentials(true);
        source.registerCorsConfiguration("/**", corsConfiguration);
        return new CorsWebFilter(source);
    }
}

3. 总结

1、Netscape公司为了保证浏览器的使用安全引用了同源策略,同源策略中规定Ajax请求只能发给同源网址,否则报错。

2、但是在实际场景下有可能需要用到跨源访问,于是W3C提出了CORS标准,允许我们通过特殊策略,进行跨源资源分享

3、CORS标准下,浏览器会对跨源请求发送预检请求,作为服务器端需要判断请求是否合法,同时响应预检请求。

参考资源

阮一峰-跨域资源共享 CORS 详解

阮一峰-浏览器同源政策及其规避方法

跨源资源共享(CORS)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值