如果你使用76+版本的chrome浏览器,通过开发者面板查看每个网络请求,会发现都有几个Sec-Fetch开头的请求头,例如访问百度首页https://www.baidu.com/的请求:

Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1

这是用来干嘛的呢,简单来说,就是网络请求的元数据描述,服务端根据这些补充数据进行细粒度的控制响应,换句话说,服务端可以精确判断请求的合法性,杜绝非法请求和攻击,提高web服务的安全性。

Fetch Metadata Request Headers

Sec-Fetch开头的请求头都属于Fetch Metadata Request Headers,于2019年发布的新草案,目前处于Editor's Draft阶段,支持度还不是很高,还需要注意的是,这些请求头都是Forbidden header,也就是不能被篡改的,是浏览器自动加上的请求头,这样也保证了数据的准确性,还需要注意的是如果资源是本地缓存加载,那么就不会添加这些请求头了,这也容易理解,就不多说了。

规范的意义

近些年web领域发展迅速,但是安全问题也十分突出,从最初浏览器的同源模型到CSP,再到Fetch Metadata Request Headers,都是对web安全不断的完善和加强,以往很多安全策略侧重于客户端的防护,服务端需要识别非法请求往往比较困难,因为缺乏判断请求的依据,控制比较粗线条,而Fetch Metadata Request Headers的出现就为服务端过滤非法请求提供了元数据,避免csrf,xssi等攻击就很容易了。

接下来探究一下这四个请求头的含义;

Sec-Fetch-Dest

含义:

表示请求的目的地,即如何使用获取的数据;

取值范围:



说明:

Dest是destination的缩写,根据上面的取值范围可很容易理解了,这个请求头指明客户端请求的目的,期望需要什么样的资源;

Sec-Fetch-Mode

含义

该请求头表明了一个请求的模式;

取值范围:

cors:跨域请求;

no-cors:限制请求只能使用请求方法(get/post/put)和请求头(accept/accept-language/content-language/content-type);

same-origin:如果使用此模式向另外一个源发送请求,显而易见,结果会是一个错误。你可以设置该模式以确保请求总是向当前的源发起的;

navigate:表示这是一个浏览器的页面切换请求(request)。 navigate请求仅在浏览器切换页面时创建,该请求应该返回HTML;

websocket:建立websocket连接;

说明:

cors表示跨域请求,且要求后端需要设置cors响应头;no-cors并不是代表请求不跨域,而是服务端不设置cors响应头,什么情况下会是这种模式呢,图片/脚本/样式表这些请求是容许跨域且不用设置跨域响应头的,而no-cors也是默认的模式;same-origin表示同源请求,这就限制了不能跨域,前面说的cors和no-cors是容许跨域的,只是要求服务端的设置不同而已,熟悉fetch接口的同学对mode属性应该不陌生,其实跟这里的含义是一样的,只是fetch的mode大家可以手动设置,而Sec-Fetch-Mode不能干预而已;

Sec-Fetch-Site

含义:

表示一个请求发起者的来源与目标资源来源之间的关系;

取值范围:

cross-site:跨域请求;

same-origin:发起和目标站点源完全一致;

same-site:有几种判定情况,详见说明;

none:如果用户直接触发页面导航,例如在浏览器地址栏中输入地址,点击书签跳转等,就会设置none;

说明:

same-site有几种情况(A->B):

A B same site
(" https ", " example.com ") (" https ", " sub.example.com ") true
(" https ", " example.com ") (" https ", " sub.other.example.com ") true
(" https ", " example.com ") (" http ", " non-secure.example.com ") false
(" https ", " r.wildlife.museum ") (" https ", " sub.r.wildlife.museum ") true
(" https ", " r.wildlife.museum ") (" https ", " sub.other.r.wildlife.museum ") true
(" https ", " r.wildlife.museum ") (" https ", " other.wildlife.museum ") false
(" https ", " r.wildlife.museum ") (" https ", " wildlife.museum ") false
(" https ", " wildlife.museum ") (" https ", " wildlife.museum ") true

在地址有重定向的情况下,Sec-Fetch-Site取值稍微复杂一点,直接参考一下示例:

1.https://example.com/ 请求https://example.com/redirect,此时的Sec-Fetch-Sitesame-origin;

2.https://example.com/redirect重定向到https://subdomain.example.com/redirect,此时的Sec-Fetch-Sitesame-site (因为是一级请求二级域名);

3.https://subdomain.example.com/redirect重定向到https://example.net/redirect,此时的Sec-Fetch-Sitecross-site (因为https://example.net/https://example.com&https://subdomain.example.com/是不同站点);

4.https://example.net/redirect重定向到https://example.com/,此时的Sec-Fetch-Sitecross-site(因为重定向地址链里包含了https://example.net/);

Sec-Fetch-User

含义:

取值是一个Boolean类型的值,true(?1)表示导航请求由用户激活触发(鼠标点击/键盘),false(?0)表示导航请求由用户激活以外的原因触发;

取值范围:

?0

?1

说明:

请求头只会在导航请求情况下携带,导航请求包括document , embed , frame , iframe , or object

安全策略

了解了上面是个请求头的含义之后,我们就可以根据项目实际情况来制定安全策略了,例如google I/O提供的一个示例:

# Reject cross-origin requests to protect from CSRF, XSSI & other bugs
def allow_request(req):
# Allow requests from browsers which don't send Fetch Metadata
if not req['sec-fetch-site']:
return True
# Allow same-site and browser-initiated requests
if req['sec-fetch-site'] in ('same-origin', 'same-site', 'none'):
return True
# Allow simple top-level navigations from anywhere
if req['sec-fetch-mode'] == 'navigate' and req.method == 'GET':
return True
return False

1.浏览器不支持Sec-Fetch-*请求头,则不做处理;

2.容许sec-fetch-sitesame-origin, same-site, none三种之一的请求;

3.容许sec-fetch-modenavigate且get请求的方法;

4.容许部分跨域请求,可设置白名单进行匹配;

5.禁止其他非导航的跨域请求,确保由用户直接发起;

在使用Fetch Metadata Request Headers时,还需要注意Vary响应头的正确设置,Vary这个响应头是干嘛的呢,其实就是缓存的版本控制,当客户端请求头中的值包含在Vary中时,就会去匹配对应的缓存版本(如果失效就会同步资源),因此针对不同的请求,能提供不同的缓存数据,可以理解为差异化服务,说明白了Vary响应头之后,就明白了Fetch Metadata Request Headers与Vary的影响关系了,因为要确保缓存能正确处理携带Sec-Fetch-*请求头的客户端响应,例如Vary: Accept-Encoding, Sec-Fetch-Site,因此有没有携带Sec-Fetch-Site将会对应两个缓存版本。

参考资料:

https://developer.mozilla.org/zh-CN/docs/Web/API/Request/mode

https://fetch.spec.whatwg.org/#concept-request-mode

https://web.dev/fetch-metadata/

https://w3c.github.io/webappsec-fetch-metadata/#intro

福禄ICH·架构组
福袋

Sec-Fetch-*请求头,了解下?的更多相关文章

  1. 解决通过Nginx转发的服务请求头header中含有下划线的key,其值取不到的问题

    1. 问题 由于在http请求头的头部中设置了一些自定义字段,刚好这些字段中含有下划线,比如bundle_name这种,后端在进去获取头部信息时,发现取不到对应的值 2. 原因及解决办法 分析 首先看 ...

  2. 前后端数据交互(四)——fetch 请求详解

    fetch 是 XMLHttpRequest 的升级版,使用js脚本发出网络请求,但是与 XMLHttpRequest 不同的是,fetch 方式使用 Promise,相比 XMLHttpReques ...

  3. HTTP请求头详解

    http://blog.csdn.net/kfanning/article/details/6062118 HTTP由两部分组成:请求和响应.当你在Web浏览器中输入一个URL时,浏览 器将根据你的要 ...

  4. HTTP协议及其请求头分析

    HTTP协议及其请求头分析 HTTP协议及其请求头分析   众所周知,Internet的基本协议是TCP/IP协议,目前广泛采用的FTP.Archie Gopher等是建立在TCP/IP协议之上的应用 ...

  5. [转]HTTP协议及其请求头分析

      众所周知,Internet的基本协议是TCP/IP协议,目前广泛采用的FTP.Archie Gopher等是建立在TCP/IP协议之上的应用层协议,不同的协议对应着不同的应用.  WWW服务器使用 ...

  6. Android系列之网络(二)----HTTP请求头与响应头

    ​[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...

  7. HTTP响应头和请求头信息对照表

    HTTP请求头提供了关于请求,响应或者其他的发送实体的信息.HTTP的头信息包括通用头.请求头.响应头和实体头四个部分.每个头域由一个域名,冒号(:)和域值三部分组成. 通用头标:即可用于请求,也可用 ...

  8. 使用PHP得到所有的HTTP请求头_还有应答头

    1)如何获取 客户端请求的头部 参考网站: http://www.neatstudio.com/show-377-1.shtml PHP中一般采用getallheaders来获取头部,但事实上,有些模 ...

  9. HTTP请求头详解【转】

    http://blog.csdn.net/kfanning/article/details/6062118 HTTP由两部分组成:请求和响应.当你在Web浏览器中输入一个URL时,浏览器将根据你的要求 ...

  10. 自定义请求头信息及cookie信息

    请求网页的时候有时候我们需要传递一些参数信息,这个时候我们可以将参数放到请求头中,具体使用如下: 这里有小问题就是请求参数的属性名好像不支持下划线,即 HTTP_UID不可用,但是HTTP-UID就可 ...

随机推荐

  1. springboot:This application has no explicit mapping for /erro

    springboot启动没有报错,但是访问的时候返回如上图的错误.看报错内容感觉是没有这个mapping对应的接口.但是确实写了. 最终发现是因为springboot的启动类放的位置不对.启动类所在的 ...

  2. 搜索引擎学习(二)Lucene创建索引

    PS:需要用到的jar包: 代码实现 1.工程结构 2.设置工程依赖的jar包 3.代码实现 /** * Lucene入门 * 创建索引 */ public class CreateIndex { / ...

  3. 微服务实战系列(四)-注册中心springcloud alibaba nacos

    1.场景描述 因要用到微服务,关于注册中心这块,与同事在技术原型上做了讨论,初步定的方案是使用:阿里巴巴的nacos+springcloud gateway,下面表格是同事整理的注册中心对比,以前用的 ...

  4. GIT学习与GIEE(码云体验)

    GIT 是一个开源的分布式版本控制系统,可以有效.高速的处理从很小到非常大的项目版本管理.Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件 ...

  5. Linux 虚拟机绑定静态 IP

    环境介绍 Machine: NUC8i5BEK OS: macOS Catalina 10.15.6 VirtualBox: 6.1.12 r139181 (Qt5.6.3) CentOS: 8.2. ...

  6. APPCNA 指纹验证登录

    今天在APP中集成了指纹与手势登录功能,本文章分两部分进行记录.一是手势功能的逻辑.二是代码实现.该APP是采用APPCAN开发,直接用其已写好的插件,调用相当接口就要可以了. 1.在APP的个人中心 ...

  7. RabbitMQ小记(四)

    1.RabbitMQ管理 (1)权限管理 物理服务器和虚拟主机都各自有独立的权限管理,用户访问需要设置权限. 授权命令:rabbitmqctl set permissions [-p vhost] { ...

  8. Spring 注解形式AOP

    AOP 面向切面编程,通过预编译的方式,在运行期通过动态代理实现一种技术,AOP可实现业务与切面的逻辑分离,降低耦合度 一.注解形式的AOP Aspect:切面 Joinpoint:连接点,要拦截的方 ...

  9. SFUD+FAL+EasyFlash典型场景需求分析,并记一次实操记录

    SFUD+FAL+EasyFlash典型场景需求分析:用整个flash存储数据,上千条数据,读取得时候用easyflash很慢,估计要检索整个flash太慢了. 改进方法:分区检索. 1存数据时,根据 ...

  10. Shiro入门学习---使用自定义Realm完成认证|练气中期

    写在前面 在上一篇文章<shiro认证流程源码分析--练气初期>当中,我们简单分析了一下shiro的认证流程.不难发现,如果我们需要使用其他数据源的信息完成认证操作,我们需要自定义Real ...