前后端分离的项目中(跨域请求 api), 如何正确使用 cookie 作为验证? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ethusdt
0.01D
V2EX    前端开发

前后端分离的项目中(跨域请求 api), 如何正确使用 cookie 作为验证?

  •  1
     
  •   ethusdt
    FaiChou 2018-12-25 08:47:57 +08:00 8680 次点击
    这是一个创建于 2484 天前的主题,其中的信息可能已经有所发展或是发生改变。

    问题相关: fetch api 在浏览器内无法保存和发送 cookie

    昨天碰到浏览器无法发送 cookie 的问题, 最后才发现是浏览器默认禁止第三方 cookie.

    Chrome / Safari / iOS Safari 都是默认禁止三方 cookie 的.

    好久之前做项目都是用 token 作为验证方式, 现在这个小项目后端使用 php5.6 seesion 形式记录用户会话.

    那么问题来了, 现在浏览器禁止了三方 cookie 还有用 cookie 作为验证的可能吗? 不可能引导用户去手动开启 cookie 权限吧?

    有啥好的替代方案? auth2?

    ps. 小项目是 react 写的界面, 放到微信里的页面.

    36 条回复    2018-12-25 12:52:29 +08:00
    lhx2008
        1
    lhx2008  
       2018-12-25 08:52:35 +08:00 via Android
    可能你对第三方 cookies 有什么误解,credientails 在跨域时是合法的,他只是把 cookies 时间弄错了。
    ethusdt
        2
    ethusdt  
    OP
       2018-12-25 08:54:35 +08:00
    @lhx2008 cookie 时间是没错的, "GMT", 我手动开启了三方 cookie 权限 是可以正常请求的.
    shijianit
        3
    shijianit  
       2018-12-25 08:55:01 +08:00
    localStore
    xyooyx
        4
    xyooyx  
       2018-12-25 08:57:54 +08:00 via iPhone
    我用 jwt,证明“我是我”就可以了
    ethusdt
        5
    ethusdt  
    OP
       2018-12-25 08:58:05 +08:00
    @lhx2008

    前后端能做的我都做过:

    前端 credentials: 'include',
    后端 Access-Control-Allow-Credentials: true + Access-Control-Allow-Origin: http://localhost:3000

    为了复现这个问题, 我在 GCP 上写了个简单的 php



    验证就是不通过..

    当我把 cookie 权限打开 就正常了.
    lhx2008
        6
    lhx2008  
       2018-12-25 08:59:04 +08:00 via Android
    @FaiChou 那就不太清楚了,我的 chrome71 和 firefox 都没问题
    ytmsdy
        7
    ytmsdy  
       2018-12-25 08:59:14 +08:00
    Http 里面的 Authorization 了解一下?
    lhx2008
        8
    lhx2008  
       2018-12-25 09:00:56 +08:00 via Android
    你可以访问下我博客 luan.ma 看看 v2.jinrishici.com 那个请求有没带 cookies 上去
    Desiree
        9
    Desiree  
       2018-12-25 09:03:02 +08:00
    @lhx2008 好奇问下,大哥你这个博客是用什么搭的,挺好看的
    Marstin
        10
    Marstin  
       2018-12-25 09:03:54 +08:00
    跨域请求的目的是干嘛呢,为什么要带 cookie,你这里既然都已经跨域了,cookie 带过去了,也能识别吗?
    lhx2008
        11
    lhx2008  
       2018-12-25 09:08:19 +08:00 via Android
    @Desiree 博客底下有,hexo 和 aircloud 主题
    ethusdt
        12
    ethusdt  
    OP
       2018-12-25 09:09:10 +08:00
    @lhx2008 好的 等我验证下.


    @Marstin 「既然都已经跨域了,cookie 带过去了,也能识别吗」没明白这句话. 我认为浏览器会自动处理某域下的 cookie
    ethusdt
        13
    ethusdt  
    OP
       2018-12-25 09:14:38 +08:00
    @lhx2008 很奇怪..



    这是 chrome 里的, 我的跨域请求的 header 都会显示 *Provisional headers are shown*. 看不到 request header 里信息. 搜过网上的方案, 都解决不了 *Provisional headers are shown* 问题.



    这是 Safari 里的, 请求会带上 cookie, 但所以请求都看过, 没有 set-cookie, 这个 request 里的 cookie 哪里来的呢?
    lhx2008
        14
    lhx2008  
       2018-12-25 09:20:04 +08:00   1
    @FaiChou 确实是我错了,如果 chrome 设置了阻止第三方 cookies,确实是发不上的。但是我用过的浏览器好像默认都不阻止。
    Provisional headers are shown 是 Chrome 的祖传 Bug,对于部分 HTTP2 的连接故意不显示,其实抓包你就发现挺正常的。
    没有 cookies 访问的时候有 set-cookies,你可以清空那个域下面的 cookies,再访问一次可能可以看到。
    所以,好一点解决方法可能是用 localstorage 了,我当初也是为这个事情绞尽脑汁。
    不过好像有些统计 js 是用浏览器指纹的技术,甚至跨浏览器都可以跟踪用户,具体我也没研究出来
    wuhuaji
        15
    wuhuaji  
       2018-12-25 09:20:11 +08:00   1
    你的 one.json 请求,返回的 cookie 没有设置 domain 属性,应该置为当前域名,也就是 luan.ma

    部分响应头如下:
    server: nginx/1.15.5
    date: Tue, 25 Dec 2018 01:17:17 GMT
    content-type: application/json;charset=
    set-cookie: X-User-Token=YAEAnG+2hPllOHE5Uwuxz8ZAzHqG7Pf/; Max-Age=7776000; Expires=Mon, 25 Mar 2019 01:17:17 GMT
    access-control-allow-origin: https://luan.ma
    access-control-allow-credentials: true
    lhx2008
        16
    lhx2008  
       2018-12-25 09:22:58 +08:00
    @wuhuaji 我想要做跨站保持同一个 cookies,以为这个是一个公开的 API,这个方法好像大多数时候是凑效的
    ethusdt
        17
    ethusdt  
    OP
       2018-12-25 09:28:34 +08:00
    @lhx2008 谢谢, 我的浏览器默认都是禁止, 在网上看到过好像因为隐私问题被欧盟一直追究, 所以很多浏览器都是默认禁止的

    在 Safari 中是 prevent cross-site tracking



    @wuhuaji 请问你是在 chrome 中看到这些信息的吗? 我的跨域请求在 chrome 中都看不到 set-cookie 字段. 我用 Charles 抓包关掉代理 luan.ma 就访问不了了

    lhx2008
        18
    lhx2008  
       2018-12-25 09:34:34 +08:00
    @FaiChou 是的,自从我升了 HTTP2 之后就不显示了,我开发的时候用 HTTP/1.1 啥事没有。但是如果不开阻止第三方的话,cookies 还是 set 到了
    lhx2008
        19
    lhx2008  
       2018-12-25 09:35:17 +08:00
    @wuhuaji domain 好像完全跨域是不能用的,我也不太清楚
    lhx2008
        20
    lhx2008  
       2018-12-25 09:39:40 +08:00
    MDN 其实也有写,我当初看到中文版没翻译到。
    https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Requests_with_credentials
    Third-party cookies
    Note that cookies set in CORS responses are subject to normal third-party cookie policies. In the example above, the page is loaded from foo.example, but the cookie on line 22 is sent by bar.other, and would thus not be saved if the user has configured their browser to reject all third-party cookies.
    lhx2008
        21
    lhx2008  
       2018-12-25 09:42:33 +08:00
    不过你可以研究下我网站上面那个 mta.qq.com 的请求,即使关闭了第三方 cookies,照样可以保持跟踪
    wu67
        22
    wu67  
       2018-12-25 09:44:54 +08:00
    额, 所以在 api 后面加?token=***不行吗
    wuhuaji
        23
    wuhuaji  
       2018-12-25 09:45:03 +08:00   1
    @lhx2008 没明白你说的 domain 跨域完全不能用什么意思? cookie 是要设置 domain 的。

    ethusdt
        24
    ethusdt  
    OP
       2018-12-25 09:49:07 +08:00
    @wuhuaji 好的 谢谢 我也试过 可以拿到

    lhx2008
        25
    lhx2008  
       2018-12-25 09:55:03 +08:00
    pingjs.qq.com 那个,很神奇,不知道有没大佬破解一下,关 cookies 重启浏览器依然可以保持不变

    lhx2008
        26
    lhx2008  
       2018-12-25 10:10:29 +08:00
    js 在 pingjsqq.com
    然后,核心代码是
    a = "pvi";
    window.localStorage ? localStorage.getItem(a) || sessionStorage.getItem(a) : (a = document.cookie.match(new RegExp("(?:^|;\\s)" + a + "=(.*?)(?:;\\s|$)"))) ? a[1] : "";
    先获取当前域下面的 localStorage,如果没有,获取 pingjsqq.com 域下面的 cookies 里面的 id,然后 set 到当前域的 localstorage,下次再读取当前域的 localstorage
    pubby
        27
    pubby  
       2018-12-25 10:22:02 +08:00 via Android
    请求时发送 cookie 是没问题的。

    只是无法保存跨域 api 发来的 cookie

    所以如果 api 域名是 abc.com 的话,你得想办法先跳转到 abc.com 去接收 cookie
    ethusdt
        28
    ethusdt  
    OP
       2018-12-25 10:24:28 +08:00
    @lhx2008 是的 在 local storage 里是有个 pgv_pvi 字段.
    ethusdt
        29
    ethusdt  
    OP
       2018-12-25 10:26:11 +08:00
    @pubby 是的, 这也是个解决方案, 但如果自己写的话内容有点多, 在这个小项目中不值得.
    lhx2008
        30
    lhx2008  
       2018-12-25 10:32:31 +08:00
    @FaiChou 他妙在用 js 域的 cookies 来存 token,兼容了浏览器不支持 localstorage 的情况,而且实现了跨域名追踪
    pubby
        31
    pubby  
       2018-12-25 10:37:42 +08:00 via Android
    @FaiChou 和项目大小无关,用 cookie 只能这么搞
    lhx2008
        32
    lhx2008  
       2018-12-25 11:00:56 +08:00
    我在 Github 上面看到一个更骚的操作,挂载一个 iframe,然后用 HTML5 的 postMessage 进行跨域通信
    lhx2008
        33
    lhx2008  
       2018-12-25 11:01:06 +08:00
    ethusdt
        34
    ethusdt  
    OP
       2018-12-25 11:09:30 +08:00
    @pubby @lhx2008

    谢谢.

    在 SO 上看到过一个~~答案~~问题 https://stackoverflow.com/questions/3342140/cross-domain-cookies
    lhx2008
        35
    lhx2008  
       2018-12-25 11:51:51 +08:00
    我总结了一下,发了个帖子
    t/520756
    EvilCult
        36
    EvilCult  
       2018-12-25 12:52:29 +08:00
    jwt 了解一下
    header 里加 Authorization
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     898 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 21:28 PVG 05:28 LAX 14:28 JFK 17:28
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86