精准解析 前后端分离 - 跨域问题

为什么会有跨域问题的出现?

提到跨域问题,我们就要了解一些浏览器的同源策略

同源策略是一个重要的安全策略,它用于限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。

它定义了在 协议 / 主机名 / 端口号 都相同的情况下的请求才为同源请求:

借鉴文章

URL结果原因
http://store.company.com/dir2/other.html同源只有路径不同
http://store.company.com/dir/inner/another.html同源只有路径不同
https://store.company.com/secure.html失败协议不同
http://store.company.com:81/dir/etc.html失败端口不同 ( http:// 默认端口是80)
http://news.company.com/dir/other.html失败主机不同

 

 

没有同源策略的危险场景

我们在浏览器中登录网站的时候,一般都是输入一次密码就好了,那是因为服务器端在登录验证完成之后,会在响应头中加入一个Set-Cookie,下次请求的时候,你HTTP请求的头字段中加入这个Cookie,服务器会自动识别用户为验证过的用户,就无需再次输入密码验证。

那么问题来,如果你正在某行网站(www.mouhang.com)查询你的“巨额资产”,正在这个时候,你多年未见的老同学给你来了个网站(www.daohao.com),手贱的你没有思考就点了下去。

点完你就会后悔了,同学一定是被盗号了!但是由于你像同学发的网站发送了一个请求,在没有同源策略的情况下,带着你Cookie的请求就发送到了www.daohao.com的网站上去,截获了你的Cookie的非法分子,通过这个请求就可以登录你的帐号了,你的“巨额资产”不翼而飞。

没错,你遭受到了CSRF攻击;没有浏览器的保护,作为小白的你很脆弱。

 

 

什么时候会有跨域问题呢?

其实不是跨域就一定存在跨域问题。

这句话看起来很矛盾,其实是因为跨域问题主要是浏览器对ajax请求的一种限制,虽然给我带了一些便,但是给我们带来了安全。

 

常见的跨域问题的解决方案?

前端:

jsonp,作为最早的解决方案,利用script标签可以跨域的原理实现。

局限:1、需要服务的支持   2、只能发起 Get 请求

 

后端:

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

优势:1、在服务器端进行跨域控制,还可以自定义规则   2、支持各种请求方式

局限:会产生额外的请求

 

 

nginx,通过反向代理,将跨域请求转换为非跨域请求

优势:支持多种请求方式

局限:需要在nginx上进行额外的配置,语义不清晰

 

解决方案

jsonp

我作为一个后端开发人员,就不给大家分享了。

CORS

之前我写过关于 spring boot 中通过 CROS 解决跨域问题的文章:传送门,其实在跨域请求的方法上加上CorsOrigin注解,也可以进行简单的跨域。

nginx

传送门

 

CORS原理知识

浏览器会把ajax请求分为两种:简单请求特殊请求

 

简单请求:

请求方法是以下三种:HEAD、GET、POST

HTTP的头信息不超过以下几种字段:Accept、Accept-Language、Cotent-Language、Last-Event-ID、Content-Type

 

当浏览器检测到ajax的请求时简单请求的时候,会在请求头上加一个字段 --->origin,origin中会指出当前请求属于哪个域(协议+域名+端口)。服务会根据这个值决定是否允许其跨域。

如果允许跨域;服务器会在返回的响应头中加入一下信息:

  • 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一定不能为*,必须是指定的域名

 

需要注意的是,CORS需要浏览器和服务器的支持,目前的话,貌似所有浏览器都支持该功能,浏览器的版本不能低于10

之前我写过关于 spring boot 中通过 CROS 解决跨域问题的文章:传送门 ,其实我们也可以通过 在被跨域请求的方法上加上 @CorsOrigin 注解进行简单的跨域操作。

 

特殊请求:

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

预检请求

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

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

预检请求的样板

OPTIONS /cors HTTP/1.1
Origin: http://www.eric.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
Host: api.leyou.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...

服务器对预检请求进行检测,如果可以跨域,会给客户端一个响应,响应样板

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2019 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://www.eric.com
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Access-Control-Max-Age: 1728000
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

 

简做总结,如果不足,欢迎指出!

 

评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值