V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
zxCoder
V2EX  ›  问与答

个人前后端分离项目中 token 是怎么处理的

  •  
  •   zxCoder · 2021-08-16 13:35:25 +08:00 · 3537 次点击
    这是一个创建于 1230 天前的主题,其中的信息可能已经有所发展或是发生改变。

    登陆后后端发一个 token,前端存在 localstorage 里,然后前端的登录状态显示是根据这个 localstorage 里的 token 吗,那这样怎么判断 token 过期了呢,前端也要再存个 token 的有效时间吗?

    29 条回复    2021-08-17 17:46:57 +08:00
    seki
        1
    seki  
       2021-08-16 13:36:55 +08:00
    后端管理 token 的有效期,给前端提示 token 过期
    xuxuxu123
        2
    xuxuxu123  
       2021-08-16 13:38:43 +08:00
    每个请求都带 token,后端接收到请求判断 token 收有效;如果 token 过期,就告诉前端例如返回 401:token 过期,前端在请求的响应拦截器全局判断请求的响应码是不是 401 ;
    SniperXu
        3
    SniperXu  
       2021-08-16 13:38:48 +08:00
    让接口告诉你有没有过期
    dfkjgklfdjg
        4
    dfkjgklfdjg  
       2021-08-16 13:44:09 +08:00   ❤️ 4
    1:基础款,后端接口拦截判断是否 token 过期,如果过期返回 401,没过期继续业务请求,前端请求拦截器内加判断;
    2:基础款 Plus,后端返回 token 之后返回过期时间,前端保存在本地,请求之前先判断是否过期,如过期直接提示,中断请求。
    zxCoder
        5
    zxCoder  
    OP
       2021-08-16 13:47:18 +08:00
    @seki
    @xuxuxu123
    @SniperXu
    @dfkjgklfdjg

    那这样岂不是会出现,前端认为 token 有效而展示对应的东西,比如没有登录注册按钮而显示个人信息按钮,但是实际上 token 已经过期了,等到发送新的请求才知道
    xuxuxu123
        6
    xuxuxu123  
       2021-08-16 14:12:30 +08:00
    @zxCoder 如果 4 楼还达不到你的要求,那么用 websocket 长连接???链接断开或者后端告知 token 失效就进登录页
    csdoker
        7
    csdoker  
       2021-08-16 14:19:14 +08:00
    @zxCoder 现在大多数网站都是这样的,必须要有新请求,前端才知道目前用户的 token 是否过期,实际上这样也没什么大问题
    Rocketer
        8
    Rocketer  
       2021-08-16 14:29:22 +08:00 via iPhone
    如果是 oauth,一般你申请 token 的时候,返回的数据里就告诉你有效期了。

    如果是 jwt,那在 payload 里一般也会记录有效期。

    你可以用这些数据在前端控制流程,但永远记住——前端控制是为了帮用户获得一个正常的体验,不要总是进入不可用的页面或者点到不可用的按钮。而不是用来限制用户,禁止他进入某个页面或者点击某个按钮。

    前端是不可信的!
    erwin985211
        9
    erwin985211  
       2021-08-16 14:44:23 +08:00
    @zxCoder 是在不行,你在 localstorage 里面存上过期时间,你前端自己判断是否过期,当然后端也要判断
    seki
        10
    seki  
       2021-08-16 14:45:31 +08:00
    @zxCoder 看到了会有什么后果呢,其实也没什么后果对吧

    每次请求都验证 token 的话,只要有一个请求前端就能知道过期

    希望让用户尽快得到过期的提示的话,可以用心跳请求
    justfindu
        11
    justfindu  
       2021-08-16 14:47:20 +08:00
    所有的需要授权认证的接口, 都肯定是接口告诉你已经过期, 并且不返回数据给你. 肯定不能是前端控制啊
    dfkjgklfdjg
        12
    dfkjgklfdjg  
       2021-08-16 14:51:53 +08:00
    @zxCoder #5,正常来说是这样的,只要用户不操作就会保持 “已登陆”状态,直到他下一次请求操作。

    亦或你自己写一个定时器,大概半个小时(自己预估)判断一次 token 状态,可以自己本地判断 token 的过期时间戳,或者用心跳 Ping 后端。
    kop1989
        13
    kop1989  
       2021-08-16 15:26:54 +08:00
    在发送新请求之前,页面的业务逻辑是静态的。所以页面其实不需要知道 token 是否过期。(除非你给 token 赋予了本不应 token 负责的业务意义)
    XTTX
        14
    XTTX  
       2021-08-16 15:29:28 +08:00
    React 的常规做法: ( session based )
    1. context 里做一个 useAuth, useAuth 请求"\auth", 后台判断用户是否登录, 已登录->返回 json:{user:xxx}以及将 session info 做到 cookie 里面。 未登录->后台不返回 user json, 前端的 user===null, 对用户显示没登陆的那一部分
    2. context 里面还有一个 useFetch, useFetch 请求"\csrf", 后台返回 csrf token, 前端将 tcsrf token 做到默认的 axios head 里面,做成"authAxios", 用 useFetch 共享给全 app
    3. 前端请求后端, 必用 useFetch 提供的 authAxios, authAxios 里包含 cookie 。 这样,后台收到的每个请求都包含 csrf 和 session cookie.
    4.后台判断 csrf 是否正确,session 是否过期,过期就返回 cookie max (-1), 前端就会删掉对应的 session cookie.


    这是一个比较成熟的做法。 前后端分离的 security 是比较难的,建议多看看成熟的项目。
    XTTX
        15
    XTTX  
       2021-08-16 15:34:45 +08:00   ❤️ 1
    如果有能力的话,建议买 reactsecurity.io 的课程,把整个 jwt 和 session 都弄明白。 大部分的大佬都会建议,能不自己做 auth 就不做, 用第三方。
    anguiao
        16
    anguiao  
       2021-08-16 15:42:02 +08:00
    和服务器交互时再判断,我觉得没有什么问题,挺合理的。
    Leviathann
        17
    Leviathann  
       2021-08-16 16:08:15 +08:00 via iPhone
    就 jwt 吧
    自带 expire 字段
    Kisesy
        18
    Kisesy  
       2021-08-16 16:28:05 +08:00
    打开网站时就主动请求一下
    copymaster
        19
    copymaster  
       2021-08-16 18:33:57 +08:00
    给你说说我的方案,用户登录成功之后,把用户信息,过期时间等等一些你觉得有用的信息放到 json 中加密发给前端,这个就是你的 token,再加上一个过期时间,用户请求的时候带上这个 token,后端解密放到 session 或 request 域中
    KouShuiYu
        20
    KouShuiYu  
       2021-08-16 18:34:51 +08:00
    我是放到 localstorage 里了
    打开网站时先判断一下 token
    https://github.com/chenkai0520/vite-template/blob/main/src/main.js#L9-L16

    发请求的时候自动带上 token
    https://github.com/chenkai0520/vite-template/blob/main/src/api/instance.js#L14-L23
    ajaxfunction
        21
    ajaxfunction  
       2021-08-16 21:37:43 +08:00
    最靠谱的就是 header 里带 token 啊,每次请求要校验 token 状态,
    还有一种 jwt,我一直觉得不好用。
    XTTX
        22
    XTTX  
       2021-08-16 22:04:17 +08:00
    @ajaxfunction header 带 token, token 可以存在内存里,避开存在 localstorage,就像 csrf token. 登录如果需要 persist, 还是要用到 cookie.
    falcon05
        23
    falcon05  
       2021-08-17 01:44:33 +08:00 via iPhone
    本地 local storage 也存一个过期时间,请求前先判断是否到期,到期直接转到登录流程,可以少一次 API 请求,同时清除 local storage 的相关数据,比如 token 。

    后端必然要做校验,jwt 本身就要检验过期时间,以防有人恶意提交或者意外提交过期的 token,单返回 401 可能不够,需要补充错误信息,有可能是请求相应资源的权限不够,比如要 VIP 才能取得访问,也可能是用户身份失效。两者处理的逻辑不一样。
    zzl22100048
        24
    zzl22100048  
       2021-08-17 08:40:37 +08:00 via iPhone
    直接用 oidc 防止不必要的烦恼
    xliao
        25
    xliao  
       2021-08-17 08:56:27 +08:00
    前端:“和服务器交互时再判断是合理的”

    后端:WTF ?
    kekxv
        26
    kekxv  
       2021-08-17 09:00:48 +08:00 via iPhone
    cookie 有什么问题吗?
    ChangJingli
        27
    ChangJingli  
       2021-08-17 11:09:55 +08:00
    前端把 token 存在 cookie 里,并设置与后端一致的 expire 时间即可。
    XTTX
        28
    XTTX  
       2021-08-17 12:49:17 +08:00
    @xliao “前端:“和服务器交互时再判断是合理的”” 这话有啥问题?
    Martin9
        29
    Martin9  
       2021-08-17 17:46:57 +08:00
    4L 说的对
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1228 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 18:06 · PVG 02:06 · LAX 10:06 · JFK 13:06
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.