求教, Android 如何实现 Token 过期后重新获取并重新进行之前的操作 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Totato5749
V2EX    Android

求教, Android 如何实现 Token 过期后重新获取并重新进行之前的操作

  •  
  •   Totato5749 2016-06-14 15:13:54 +08:00 19658 次点击
    这是一个创建于 3411 天前的主题,其中的信息可能已经有所发展或是发生改变。

    公司的项目,用户在客户端登陆后后台会给用户一个 token ,以后每次执行与用户身份有关的操作都需要向服务器带上这个 token,这个 token 在一定时间后失效,这时进行与用户身份有关的操作时会返回 token 期错误提示。

    之前我在处理这个问题时,遇到操作返回 token 过期错误,我会让用户强制重新登录。不过这个处理对用户来说体验很差,基本相当于每天都要重新登录。

    token 过期有以下几个原因:

    1. token 时间到期
    2. 用户在其他设备登录,原来设备中的 token 就会过期
    3. 其他异常等

    我想要实现的功能是: 在某次网络操作时,当服务器返回 token 过期错误后,如何实现重新获取 token 后再次尝试之前的网络操作,不让用户察觉到中间的断裂感。

    求各位大侠指教,小弟跪谢

    14 条回复    2016-06-15 10:26:21 +08:00
    Ouyangan
        1
    Ouyangan  
       2016-06-14 15:22:52 +08:00
    那就自动帮用户登录一次 .
    Totato5749
        2
    Totato5749  
    OP
       2016-06-14 15:24:01 +08:00
    @Ouyangan
    嗯,重点不是我如何再次获取 token ,而是重新获取到 token 后重复 token 过期前的那次网络操作。
    cxe2v
        3
    cxe2v  
       2016-06-14 15:37:32 +08:00
    生成 token 的时候把 token 的过期时间记下来,在过期时间后就再去获取新的 token
    fds
        4
    fds  
       2016-06-14 15:47:49 +08:00
    把操作记录下来呗……
    Totato5749
        5
    Totato5749  
    OP
       2016-06-14 15:52:49 +08:00
    @cxe2v
    问题在于有些 token 过期的原因并不是单纯的因为 token 到期,这样判断是不准确的
    eminemcola
        6
    eminemcola  
       2016-06-14 16:06:55 +08:00
    当返回 token 过期错误时,在 onError 中重新做获取 token 请求,再在获取成功的 callback 中重复用户过期前的操作。这中间的错误提示不显示给用户,对用户来说就是等得更久了点吧。应该可以避免察觉到你所说的断裂感?
    hsj1992
        7
    hsj1992  
       2016-06-14 16:51:24 +08:00
    @Totato5749
    @cxe2v 指的是对应 [用户只是单纯的在同一台设备上使用到 token 到期] 的情况,这应该是“ token 到期”的大头。
    撕裂感是因为“出错>处理”产生的时间,那么,不能从源头“减少 token 到期错误”入手么?
    magicdawn
        8
    magicdawn  
       2016-06-14 17:03:26 +08:00
    @Ouyangan

    怎么帮登录? 存密码?
    Ouyangan
        9
    Ouyangan  
       2016-06-14 17:35:04 +08:00
    @magicdawn 用户登录的时候你把 usename,password 存储下来 ,token 无效的时候,自己帮用户提交一次登录,根据服务器返回的信息判断 token 是否有效,然后进行下一步操作.
    tinyproxy
        10
    tinyproxy  
       2016-06-14 18:19:11 +08:00 via iPhone
    1. 让服务器给 refresh token ,用来获取新的 token ,不然就让后端把 ttl 弄长一点。
    2. 你们啥业务这么容易登录过期啊,没啥要紧的东西后端调整 ttl 也就几分钟的事情,你们要业务非常重要,那你这种尝试自动提交账号密码登录简直就是作死。
    3. 说存账号密码的,从安全性来说这是个下策
    tinyproxy
        11
    tinyproxy  
       2016-06-14 18:21:27 +08:00 via iPhone
    至于你说的其他设备登录,当前设备 token 过期,也让后端把单点登录限制去了,不同意让产品跟他撕逼,你也用不着管,锅一下子就甩干净了
    ki41foo
        12
    ki41foo  
       2016-06-14 22:31:18 +08:00
    如果 token 只能通过登录获取的话,只能存帐号密码自动登录了啊。
    ifane
        13
    ifane  
       2016-06-15 08:25:36 +08:00
    我做模拟登录教务系统的时候,cookie 会过期,解决办法我就只能要做啥操作前,判断 cookie 有没有过期,如果过期了就只能重新模拟登录了
    dearmadman
        14
    dearmadman  
       2016-06-15 10:26:21 +08:00
    /**
    * 资源获取帮助类,需求:
    * 1. 常用请求方法
    * 2. 自动发送请求头
    * 3. 根据状态码进行刷新 token
    * 4. 刷新 token 后自动请求上次请求内容
    * 5. refresh token 过期时提示登录
    * 6. 请求方法返回: 状态码 无论 500 还是 0 都会返回 API 内容, token 过期刷新失败直接返回 false
    */
    import storage from './storage.js'
    import api from './api.js'br />
    var http = {
    $http: {},
    config ($http) {
    this.$http = $http
    },
    http (url, data, options, method) {
    return this.$http({url: url, method: method, data: data, options: this.autoHeaders(options)}).then((res) => {
    let body = res.data
    let status = body.status.code
    if (status === 401) {
    return this.refresh().then((res) => {
    if (res) return this.http(url, data, options, method)
    return false
    })
    }
    return body
    })
    },
    get (url, data, options) {
    return this.http(url, data, options, 'GET')
    },
    post (url, data, options) {
    return this.http(url, data, options, 'POST')
    },
    delete (url, data, options) {
    return this.http(url, data, options, 'DELETE')
    },
    put (url, data, options) {
    return this.http(url, data, options, 'PUT')
    },
    refresh () {
    this.$http.post(api.refresh, null, this.autoHeaders()).then((res) => {
    if (res.data.status.code === 0) {
    this.storage.setItem('token', res.data.data.token)
    return true
    }
    return false
    })
    },
    autoHeaders (optiOns= {}) {
    return Object.assign({}, {
    headers: {
    Authorization: `Bearer ${storage.getItem('token')}`
    }
    }, options)
    }
    }

    export default http


    这么写可以吗? 有哪些糟点?
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2917 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 23ms UTC 13:29 PVG 21:29 LAX 06:29 JFK 09:29
    Do have faith in what you're doing.
    ubao msn 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