记一次 .NET Framework 不兼容 HTTP COOKIE 协议标准的问题跟踪

我们在后端系统实现了 HTTP 请求的代理类,用于请求其他第三方系统。大致的请求流程是这样的:

消费系统不能直接请求业务系统的 HTTP 接口,需要由中间的 HttpHelper 代理请求。其中 HttpHelper 接受消费系统传入的各种参数,包括要请求的 URL、METHOD、HEAD、BODY 等,在实际生产中一直运行得很好,直到如下异常的出现:

System.Net.CookieException: Cookie format error.
at System.Net.CookieContainer.CookieCutter(Uri uri, String headerName, String setCookieHeader, Boolean isThrow)

跟进异常信息,很容易知道是设置 Cookie 时发生的异常。根据请求端传入的 HEAD 信息排查,我们很容易还原故障现场:传入 HTTP 头信息 Cookie: expires=Fri, 15 Jun 2018 15:19:14 GMT

这里是在设置 Cookie 的过期时间,并且这个时间看起来也正常,并没有格式错误或者时间不存在的错误。看起来问题不出在时间本身上。上网查查 HTTP 规范,根据 HTTP Cookie 协议,也是允许如下形式的字符串的,看起来也没有什么问题:

Set-Cookie: sessionToken=abc123; Expires=Wed, 09 Jun 2021 10:18:14 GMT

既然异常是微软代码抛出来的,也给了具体抛出异常的方法的地方,那么我们就来翻翻微软代码吧。终于,在微软代码 System.Net.Cookie.VerifySetDefaults:L382 发现了问题所在。在这里,微软在校验 Cookie 值时,如果发现指定的值字符串中有保留字符(“,”、";"),则要求该值必须使用双引号引起来,否则就会抛出异常。查看我们请求的头,在 expires 的值“Fri, 15 Jun 2018 15:19:14 GMT”中,的确有“,”存在,并且值也并未使用双引号引起来。于是我尝试修改传入的 HTTP 头参数:

Cookie: expires=“Fri, 15 Jun 2018 15:19:14 GMT”

很自然,异常不再存在了,目前看起来的确是微软的这段代码导致了抛出异常。

你们我们来看看,这个值到底是不是可以去加双引号吧。继续上网翻文档,在 rfc2965#section-3.1 和 rfc6265#section-4.1.1 中提到,值可以是字符串或引号引起来的字符串(quoted-string),这是 在 HTTP State Management Mechanism 中有所规定的。那么我们可以很放心地做这个兼容性处理了,即,当传入的 Cookie 值包含保留字符,并且未被双引号引起来时(一定会产生异常),我们自动地追加双引号,把值引起来,这样既可避免微软对值进行严格校验时抛出异常了。

但是,此事还没有到此为止,我们实际来试试,加了双引号之后,业务系统是否能够正确收到消费系统传入的头呢?收到的头,是否为消费系统的正确意图呢?

值得注意的是,在业务系统里获取到的 Cookie 值,是添加了引号的值,并不是严格地与消费系统里传入的文本一致。

到此为止,应对这个异常便有两个方案了:

  1. 传入的 Cookie 值包含保留字符,并且未被双引号引起来时(一定会产生异常),我们自动地追加双引号。
  2. 什么都不做,按原意抛出异常,提醒调用者更正 HTTP 头信息的格式。

在我们的项目中,由于情况特殊(使用场景为后端服务之间的通信交互),一般不涉及到 Cookie 的设置,并且消费服务可能由很多个不同的团队实现,而业务服务可以统一处理添加的双引号,因此我们采用了方案 1。至于其他场景,实际上个人偏向于采用方案 2,不掩盖任何问题——特别是因为加了双引号之后,请求接受端接收到的值,不能完全原样表达请求发起端设置的值。

参考:

[1] https://en.wikipedia.org/wiki/HTTP_cookie [2] https://referencesource.microsoft.com/#System/net/System/Net/cookie.cs,67f8e4d3cb862668 [3] https://referencesource.microsoft.com/#System/net/System/Net/cookie.cs,dca3e494aed8e006 [4] https://tools.ietf.org/html/rfc6265#section-4.1.1 [5] https://tools.ietf.org/html/rfc2965#section-3.1 [6] https://tools.ietf.org/html/rfc2616

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏智能计算时代

Envoy 架构概览(1):术语,线程模型,监听器和网络(L3 / L4)过滤器和HTTP连接管理

术语 在我们深入到主要的体系结构文档之前,有一些定义。有些定义在行业中有些争议,但是它们是Envoy在整个文档和代码库中如何使用它们的,因此很快就会出现。 主机...

2993
来自专栏hbbliyong

你真的了解如何将 Nginx 配置为Web服务器吗

阅读之前,建议先阅读初识 Nginx。 之后,我们来了解一下 Nginx 配置。 抽象来说,将 Nginx 配置为 Web 服务器就是定义处理哪些 URLS 和...

3787
来自专栏iKcamp

走进Node.js 之 HTTP实现分析

作者:正龙(沪江Web前端开发工程师) 本文为原创文章,转载请注明作者及出处 上文“走进Node.js启动过程”中我们算是成功入门了。既然Node.js的强...

2546
来自专栏Java技术

浅谈Nginx服务器的内部核心架构设计!

Nginx---Ngine X,是一款免费的、自由的、开源的、高性能HTTP服务器和反向代理服务器;也是一个IMAP、POP3、SMTP代理服务器;Nginx以...

612
来自专栏开源优测

[接口测试 - http.client篇] 15 常用API说明及基本的示例

概述 在http.client模块中,我们主要使用HTTPConnection和HTTPResponse对象来处理整个HTTP交互过程,所以我们接下里主要介绍以...

4387
来自专栏Pythonista

粘包现象

让我们基于tcp先制作一个远程执行命令的程序(1:执行错误命令 2:执行ls 3:执行ifconfig)

522
来自专栏java思维导图

【 CDN 最佳实践】CDN 命中率优化思路

CDN 在静态资源的加速场景中是将静态资源缓存在距离客户端较近的CDN 节点上,然后客户端访问该资源即可通过较短的链路直接从缓存中获取资源,而避免再通过较长的链...

642
来自专栏Java技术栈

通用唯一标识码UUID的介绍及使用。

什么是UUID? UUID全称:Universally Unique Identifier,即通用唯一识别码。 UUID是由一组32位数的16进制数字所构成,是...

43915
来自专栏北京马哥教育

[干货]集群基础理论讲解|By黑白子童鞋

背景 随着互联网访问量的急剧增加,单台服务器的能力已严重不能满足需求。则需要从两个方面考虑提高服务能力:1、向上扩展,2、向外扩展 向上扩展的缺点: 1、造价高...

3249
来自专栏ImportSource

扒扒HTTP缓存

摘要: 本文会从理论和实战两方面描述http缓存。理论层面会介绍:缓存命中、缓存丢失、Revalidations(重新验证)、命中率(Hit Rate)、字节...

3256

扫码关注云+社区