日常踩坑中遇到的cookie问题: 跨域,特殊字符

这篇文章主要用于记录自己平时开发遇到的cookie相关的问题. 如跨域设置cookie, cookie特殊字符被截断, 中文cookie导致报错.

如果对cookie不太了解, 推荐这篇文章, 很详细
浏览器系列之 Cookie 和 SameSite 属性

跨域设置cookie

这个场景一般是在账号打通中会遇到,两个系统使用同一个账号体系,但是不同的域名。登陆一个系统的时候自动登陆到另一个系统。例如在 a.com 下同时把 cookie 设置到 b.com 下。

一般的处理方式是:在登陆完成之后,返回另一个域的setCookieUrl和获取cookie的信息(可以是加密的cookie,或者是把cookie存入缓存返回key,保证随机且复杂的key,且过期时间尽可能短)。
然后再让前端发起另一个域的异步请求设置cookie。 (在 a 的域下请求 b 域的url并设置cookie)

但是对于 chrome80 之后的版本,chrome默认不支持跨域设置cookie。解决方式有两个:

  • 引导用户设置浏览器支持三方cookie,以及在 chrome://flags 下面修改以下两项设置. 大概的做法就是:在登陆前,先发一个跨域设置cookie的请求,再发一个请求判断是否设置成功. 不成功就引导用户去修改浏览器设置.

  • 在 cookie 中添加 SameSite=None; Secure 字段,且必须使用 https协议. 不能直接用 Cookie 类, Cookie无SameSite属性. 需手动在response header 中设置,如:
    response.addHeader("Set-Cookie", "key=name; SameSite=None; Secure")

但是, 对于部分浏览器(如ios微信内置浏览器) 仍然不支持跨域设置cookie. 这个时候就只能先跳到相同的域名的中间页下面, 再请求setCookieUrl, 然后再回到之前的页面. 流程比上面要多一些.

cookie 包含特殊字符导致被截断

如:
header中: cookie:"key=value@1234"
然后使用 HttpServletRequest.getCookies 得到的cookie的则是key=value。实际上完整的value还是存在header中.

这个主要原因是使用了 LegacyCookieProcessor 作为 cookie处理器,value包含以下特殊字符会被截断。

// Excludes '/' since configuration controls whether or not to treat '/' as
// a separator
private static final char[] HTTP_SEPARATORS = new char[] {
        '\t', ' ', '\"', '(', ')', ',', ':', ';', '<', '=', '>', '?', '@',
        '[', '\\', ']', '{', '}' };  

推荐一篇相关的文章: https://juejin.cn/post/6844903918330183694

看完这篇文章,我猜可能就是前面的人因为setCookie的时候在 domain 里面加了 . 才改成 LegacyCookieProcessor的, 但其实没必要, domain前面根本不用加. .

解决方式:

  • 不在cookie中使用特殊字符
  • 不使用LegacyCookieProcessor。
  • 自己从 request 的 header 读取 Cookie,然后自己解析

因为cookie是外部传来的, 不能修改cookie. 这里选择第三种方式, 影响范围小,风险最小.

private static List<Cookie> parseCookies(HttpServletRequest request) {
        String cookieStr = request.getHeader("Cookie");
        if (StringUtils.isEmpty(cookieStr)) {
            return Collections.emptyList();
        }
        List<Cookie> cookies = new ArrayList<Cookie>();
        String[] cks = cookieStr.split(";");
        for (String ckStr : cks) {
            try {
                String[] ck = ckStr.trim().split("=", 2);
                if (ck.length<2) continue;
                Cookie cookie = new Cookie(ck[0], ck[1]);
                cookies.add(cookie);
            } catch (Exception e) {
                log.error("parseCookies error.", e);
            }
        }
        return cookies;
    }

cookie 中有中文导致后端报错

cookie中最好不要用中文, 否则服务端可能处理不了导致报错. 具体原因也是上面那个 LegacyCookieProcessor 解析cookie时抛出的异常.

注意: 不仅自己不要使用中文cookie, 也要注意前端有没有给传中文cookie!

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值