Openresty网关Cookie解析失败问题分析。

背景

Staging 环境用户报相关接口登陆态校验失败。从日志来看,是缺少了SPC_SC_TK_TS cookie导致的,但是从网关的日志来看,实际上是有对应的cookie的,原始日志如下:

info.log:2022-07-26 10:47:07|[debug ]|b4aaf75734b47456a1b019b0409a9f10|raw request: method=GET   headers={"host":"seller.staging.shopee.sg","x-real-host":"seller.staging.shopee.sg","x-real-ip":"10.129.101.101","x-now":"1658803627.911","x-forwarded-protocol":"https","x-forwarded-proto":"https","cookie":"Expires=Fri, 23 Jul 2032 02:47:07 GMT;SPC_SC_TK_TS=e20a6a31440ddf9be87c689855dd4ac0;SC_SSO_U=-;SC_DFP=pCKocNshbCOpOkAHivhynQEIdZhhZbBT;SPC_SC_UD_TS=101892977; Domain=staging.shopee.sg;SPC_U=101892977; Path=\/; Max-Age=315360000;SPC_SC_SA_TK_TS=;SPC_ST=.ZE5CRUVOMUMyam1yaDJoSJhrb7A4vidmGDXaba3rXEteQdczjo5tuMktfwMyJj\/+GPsJOI24l6m1gKTjR51CGHMrtNtvNXKxUfP0cALYdPZKyBqGqZ7zZL+EPu\/yNqTaIb0PfjAzr3k2b5BkdGdlXKAxiMx4wkR2CbBt0888aHnvTn8mBjyW3odfuJSqlMiTIyjkQomTxtJ\/mm5sWSfedQ==;SPC_STK=4s0q5hpXiWcS5KQWyg7OQtuYQetUM\/lMLVV\/EA7DpBKwmApUIdCneSPaohuYz2EGc6TsDxSXKQAoobFt2kwHRc0yHLHuvPY2Lih+zkQuZRREW9TqKMyHAOOD3\/37o2z6PB5lzAFjvj\/bWLooZko6IYg2bhLI08r2Qmrh68R54KrrNgLJd2c1yhimtBYuaNsI;SPC_F=bYmcuEZXwbPgUAAgquJLRKNcBJARkaOc;SPC_WST=Qk1fizFIQmC3AHphC0ZEHPZoDfpOxCxh1xL26zQbB\/7l0iCznh6DG724c7U5zE\/Ig+DB4x4xvXj052XoEEPOUyOAIyQR8juMQPoMtbVLIdwi\/C15DtAIjYK2+vklcyflDfKoFmg21YP8x7EHzZ6G68ygRicq96tOZGlWGYk6zZ8=;SPC_SC_SA_UD_TS=;SPC_EC=Qk1fizFIQmC3AHphC0ZEHPZoDfpOxCxh1xL26zQbB\/7l0iCznh6DG724c7U5zE\/Ig+DB4x4xvXj052XoEEPOUyOAIyQR8juMQPoMtbVLIdwi\/C15DtAIjYK2+vklcyflDfKoFmg21YP8x7EHzZ6G68ygRicq96tOZGlWGYk6zZ8=;SC_SSO=-;","x-forwarded-for":"143.92.118.24, 10.129.101.101","user-agent":"Apache-HttpClient\/4.5.10 (Java\/1.8.0_333)","accept-encoding":"gzip,deflate"}   query_string={"show_customize":"true","supplier_id":"1"}   body=nil

排查过程

发现cookie里面有奇怪的原本属于cookie的属性也被当成cookie key给传进来了

image.png

同时根据wen.yang实际测试,把Expire的空格去掉,请求就正常了。或者把SPC_SC_TK_TS放到最后,也能成功。

所以猜测可能是gateway这边解析cookie的时候,可能解析出现了问题。

|

-- lua.resty.cookie.lua
local function get_cookie_table(text_cookie)
    --忽略相关代码
    while j <= len do
        if state == EXPECT_KEY then
            if byte(text_cookie, j) == EQUAL then
                key = sub(text_cookie, i, j - 1)
                state = EXPECT_VALUE
                i = j + 1
            end
        elseif state == EXPECT_VALUE then
            if byte(text_cookie, j) == SEMICOLON
                    or byte(text_cookie, j) == SPACE  -- 问题的关键出现在这里,lua回同时使用分号、空格、制表符作为分割符来拆分cookie 对。
                    or byte(text_cookie, j) == HTAB
            then
                value = sub(text_cookie, i, j - 1)
                cookie_table[key] = value

                key, value = nil, nil
                state = EXPECT_SP
                i = j + 1
            end
        elseif state == EXPECT_SP then
            if byte(text_cookie, j) ~= SPACE
                and byte(text_cookie, j) ~= HTAB
            then
                state = EXPECT_KEY
                i = j
                j = j - 1
            end
        end
        j = j + 1
    end

    --忽略相关代码

    return cookie_table
end</pre>

按照上面的代码解析出来的cookie table,第一个cookie和第二个cookie的键值对是这样的:

理想中的解析:
Key: Expires        Value:Fri, 23 Jul 2032 02:47:07 GMT
Key: XXXX   Value:e20a6a31440ddf9be87c689855dd4ac0

实际中的解析:
Key: Expires                                 Value:Fri,
Key: 23 Jul 2032 02:47:07 GMT;SPC_SC_TK_TS   Value:e20a6a31440ddf9be87c689855dd4ac0

所以这导致了跟在Exipire 后面的那个cookie会解析失败。

同时查看RFC文档,发现其实Cookie的Value是不允许包含空格、双引号、逗号、分号和反斜杠。

image.png

建议

1.如果需要设置cookie,建议像gin提供的setCookie方法一样,将value进行urlencode。

2.如果确实不能urlencode,也最好确保cookie value里面排出了RFC文档里不允许出现的字符。至少保证不要有空格分号制表符

引用附录

RFC 6265

lua-resty-cookie

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • HTTP 协议在网络知识中占据了重要的地位,HTTP 协议最基础的就是请求和响应的报文,而报文又是由报文头(Hea...
    weifansym阅读 916评论 0 0
  • 转载出处 一、序 HTTP 协议在网络知识中占据了重要的地位,HTTP 协议最基础的就是请求和响应的报文,而报文又...
    Just丶Go阅读 617评论 0 0
  • 原文链接:https://segmentfault.com/a/1190000004556040[https://...
    R_X阅读 434评论 0 1
  • HTTP cookie(也称为web cookie,网络cookie,浏览器cookie或者简称cookie)是网...
    留七七阅读 18,117评论 2 71
  • WebAPI lesson_1——接口定义与http 一、WebAPI 1、接口定义 接口是个比较泛义上的概念,主...
    Here_Nicole阅读 124评论 0 0