背景
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文档里不允许出现的字符。至少保证不要有空格、分号和制表符