业务场景

在前后分离场景下,越来越多的项目使用token作为接口的安全机制,APP端或者WEB端(使用VUE、REACTJS等构建)使用token与后端接口交互,以达到安全的目的。本文结合stackover以及本身项目实践,试图总结出一个通用的,可落地的方案。

基本思路

  • 单个token
  1. token(A)过期设置为15分钟
  2. 前端发起请求,后端验证token(A)是否过期;如果过期,前端发起刷新token请求,后端设置已再次授权标记为true,请求成功
  3. 前端发起请求,后端验证再次授权标记,如果已经再次授权,则拒绝刷新token的请求,请求成功
  4. 如果前端每隔72小时,必须重新登录,后端检查用户最后一次登录日期,如超过72小时,则拒绝刷新token的请求,请求失败
  • 授权token加上刷新token

用户仅登录一次,用户改变密码,则废除token,重新登录

1.0实现

1.登录成功,返回access_token和refresh_token,客户端缓存此两种token;
2.使用access_token请求接口资源,成功则调用成功;如果token超时,客户端
携带refresh_token调用中间件接口获取新的access_token;
3.中间件接受刷新token的请求后,检查refresh_token是否过期。
如过期,拒绝刷新,客户端收到该状态后,跳转到登录页;
如未过期,生成新的access_token和refresh_token并返回给客户端(如有可能,让旧的refresh_token失效),客户端携带新的access_token重新调用上面的资源接口。
4.客户端退出登录或修改密码后,调用中间件注销旧的token(使access_token和refresh_token失效),同时清空客户端的access_token和refresh_toke。

后端表
id user_id client_id client_secret refresh_token expire_in create_date del_flag

2.0实现

场景: access_token访问资源 refresh_token授权访问 设置固定时间X必须重新登录

1.登录成功,后台jwt生成access_token(jwt有效期30分钟)和refresh_token(jwt有效期15天),并缓存到redis(hash-key为token,sub-key为手机号,value为设备唯一编号(根据手机号码,可以人工废除全部token,也可以根据sub-key,废除部分设备的token。),设置过期时间为1个月,保证最终所有token都能删除),返回后,客户端缓存此两种token;
2.使用access_token请求接口资源,校验成功且redis中存在该access_token(未废除)则调用成功;如果token超时,中间件删除access_token(废除);客户端再次携带refresh_token调用中间件接口获取新的access_token;
3.中间件接受刷新token的请求后,检查refresh_token是否过期。
如过期,拒绝刷新,删除refresh_token(废除); 客户端收到该状态后,跳转到登录页;
如未过期,检查缓存中是否有refresh_token(是否被废除),如果有,则生成新的access_token并返回给客户端,客户端接着携带新的access_token重新调用上面的资源接口。
4.客户端退出登录或修改密码后,调用中间件注销旧的token(中间件删除access_token和refresh_token(废除)),同时清空客户端侧的access_token和refresh_toke。
5.如手机丢失,可以根据手机号人工废除指定用户设备关联的token。
6.以上3刷新access_token可以增加根据登录时间判断最长X时间必须重新登录,此时则拒绝刷新token。(拒绝的场景:失效,长时间未登录,频繁刷新)

2.0 变动
1.登录
2.登录拦截器
3.增加刷新access_token接口
4.退出登录
5.修改密码

3.0实现

场景:自动续期 长时间未使用需重新登录

1.登录成功,后台jwt生成access_token(jwt有效期30分钟),并缓存到redis(hash-key为access_token,sub-key为手机号,value为设备唯一编号(根据手机号码,可以人工废除全部token),设置access_token过期时间为7天,保证最终所有token都能删除),返回后,客户端缓存此token;

2.使用access_token请求接口资源,校验成功且redis中存在该access_token(未废除)则调用成功;如果token超时,中间件删除access_token(废除),同时生成新的access_token并返回。客户端收到新的access_token,
再次请求接口资源。

3.客户端退出登录或修改密码后,调用中间件注销旧的token(中间件删除access_token(废除)),同时清空客户端侧的access_token。

4.以上2 可以增加根据登录时间判断最长X时间必须重新登录,此时则拒绝刷新token。(拒绝的场景:长时间未登录,频繁刷新)

5.如手机丢失,可以根据手机号人工废除指定用户设备关联的token。

3.0 变动

1.登录
2.登录拦截器
3.退出登录
4.修改密码

1.3 场景:token过期重新登录 长时间未使用需重新登录

1.登录成功,后台jwt生成access_token(jwt有效期7天),并缓存到redis,key为 "user_id:access_token",value为access_token(根据用户id,可以人工废除指定用户全部token),设置缓存过期时间为7天,保证最终所有token都能删除,请求返回后,客户端缓存此access_token;

2.使用access_token请求接口资源,校验成功且redis中存在该access_token(未废除)则调用成功;如果token超时,中间件删除access_token(废除),同时生成新的access_token并返回。客户端收到新的access_token,
再次请求接口资源。

3.客户端退出登录或修改密码后,调用中间件注销旧的token(中间件删除access_token(废除)),同时清空客户端侧的access_token。

4.以上2 可以增加根据登录时间判断最长X时间必须重新登录,此时则拒绝刷新token。(拒绝的场景:长时间未登录,频繁刷新)

5.如手机丢失,可以根据手机号人工废除指定用户设备关联的token。

1.3 变动

1.登录
2.登录拦截器
3.退出登录
4.修改密码

解决方案

2.0 场景: access_token访问资源 refresh_token授权访问 设置固定时间X必须重新登录

1.登录成功,后台jwt生成access_token(jwt有效期30分钟)和refresh_token(jwt有效期15天),并缓

存到redis(hash-key为token,sub-key为手机号,value为设备唯一编号(根据手机号码,可以人工废除全

部token,也可以根据sub-key,废除部分设备的token。),设置过期时间为1个月,保证最终所有token都

能删除),返回后,客户端缓存此两种token;

2.使用access_token请求接口资源,校验成功且redis中存在该access_token(未废除)则调用成功;如果

token超时,中间件删除access_token(废除);客户端再次携带refresh_token调用中间件接口获取新的

access_token;

3.中间件接受刷新token的请求后,检查refresh_token是否过期。

如过期,拒绝刷新,删除refresh_token(废除); 客户端收到该状态后,跳转到登录页;

如未过期,检查缓存中是否有refresh_token(是否被废除),如果有,则生成新的access_token并返回给

客户端,客户端接着携带新的access_token重新调用上面的资源接口。

4.客户端退出登录或修改密码后,调用中间件注销旧的token(中间件删除access_token和refresh_token(

废除)),同时清空客户端侧的access_token和refresh_toke。

5.如手机丢失,可以根据手机号人工废除指定用户设备关联的token。

6.以上3刷新access_token可以增加根据登录时间判断最长X时间必须重新登录,此时则拒绝刷新token。(

拒绝的场景:失效,长时间未登录,频繁刷新)

2.0 变动

1.登录

2.登录拦截器

3.增加刷新access_token接口

4.退出登录

5.修改密码

3.0 场景:自动续期 长时间未使用需重新登录

1.登录成功,后台jwt生成access_token(jwt有效期30分钟),并缓存到redis(hash-key为

access_token,sub-key为手机号,value为设备唯一编号(根据手机号码,可以人工废除全部token,也可以

根据sub-key,废除部分设备的token。),设置access_token过期时间为1个月,保证最终所有token都能删

除),返回后,客户端缓存此token;

2.使用access_token请求接口资源,校验成功且redis中存在该access_token(未废除)则调用成功;如果

token超时,中间件删除access_token(废除),同时生成新的access_token并返回。客户端收到新的

access_token,

再次请求接口资源。

3.客户端退出登录或修改密码后,调用中间件注销旧的token(中间件删除access_token(废除)),同时清

空客户端侧的access_token。

4.以上2 可以增加根据登录时间判断最长X时间必须重新登录,此时则拒绝刷新token。(拒绝的场景:长

时间未登录,频繁刷新)

5.如手机丢失,可以根据手机号人工废除指定用户设备关联的token。

3.0 变动

1.登录

2.登录拦截器

3.退出登录

4.修改密码

4.0 场景:token过期重新登录 长时间未使用需重新登录

1.登录成功,后台jwt生成access_token(jwt有效期7天),并缓存到redis,key为

"user_id:access_token" + 用户id,value为access_token(根据用户id,可以人工废除指定用户全部

token),设置缓存过期时间为7天,保证最终所有token都能删除,请求返回后,客户端缓存此

access_token;

2.使用access_token请求接口资源,校验成功且redis中存在该access_token(未废除)则调用成功;如果

token超时,中间件删除access_token(废除),同时生成新的access_token并返回。客户端收到新的

access_token,

再次请求接口资源。

3.客户端退出登录或修改密码后,调用中间件注销旧的token(中间件删除access_token(废除)),同时清

空客户端侧的access_token。

4.以上2 可以增加根据登录时间判断最长X时间必须重新登录,此时则拒绝刷新token。(拒绝的场景:长

时间未登录,频繁刷新)

5.如手机丢失,可以根据手机号人工废除指定用户设备关联的token。

4.0 变动

1.登录

2.登录拦截器

3.退出登录

4.修改密码

最终实现

后端

  1. 在登录接口中 如果校验账号密码成功 则根据用户id和用户类型创建jwt token(有效期设置为-1,即永不过期),得到A
  2. 更新登录日期(当前时间new Date()即可)(业务上可选),得到B
  3. 在redis中缓存key为ACCESS_TOKEN:userId:A(加上A是为了防止用户多个客户端登录 造成token覆盖),value为B的毫秒数(转换成字符串类型),过期时间为7天(7 * 24 * 60 * 60)
  4. 在登录结果中返回json格式为{"result":"success","token": A}
  5. 用户在接口请求header中携带token进行登录,后端在所有接口前置拦截器进行拦截,作用是解析token 拿到userId和用户类型(用户调用业务接口只需要传token即可), 如果解析失败(抛出SignatureException),则返回json(code = 0 ,info= Token验证不通过, errorCode = '1001'); 此外如果解析成功,验证redis中key为ACCESS_TOKEN:userId:A 是否存在 如果不存在 则返回json(code = 0 ,info= 会话过期请重新登录, errorCode = '1002'); 如果缓存key存在,则自动续7天超时时间(value不变),实现频繁登录用户免登陆。
  6. 把userId和用户类型放入request参数中 接口方法中可以直接拿到登录用户信息
  7. 如果是修改密码或退出登录 则废除access_tokens(删除key)

前端(VUE)

    1. 用户登录成功,则把username存入cookie中,key为loginUser;把token存入cookie中,key为accessToken 把token存入Vuex全局状态中
    2. 进入首页

文章摘自 花间_拾零的个人空间https://my.oschina.net/odetteisgorgeous/blog/1920762

JWT生成token及过期处理方案的更多相关文章

  1. 国服最强JWT生成Token做登录校验讲解,看完保证你学会!

    转载于:https://blog.csdn.net/u011277123/article/details/78918390 Free码农 2017-12-28 00:08:02 JWT简介 JWT(j ...

  2. 利用jwt生成token,用于http请求身份验证

    前段时间在做移动端接口过程中,考虑到安全性,所有移动端发送请求(除了登录请求)过程中进行token有效验证. 1.利用jwt生成token a.导入jwt相关包 <!-- jwt --> ...

  3. 使用 JWT 生成 Token 代码示例

    JSON Web Token,简称 JWT, 是一个开放的标准(RFC 7519),它定义了以一种紧凑的.自包含的 JSON 对象在各方之间安全传输信息的方式.该信息含有数字签名,可以被验证和信任. ...

  4. Token_使用JWT生成token

    1.token三部分 header   { "typ": "JWT", "alg": "HS256"   } paylo ...

  5. tp5使用jwt生成token,做api的用户认证

    首先 composer 安装  firebase/php-jwt github:https://github.com/firebase/php-jwt composer require firebas ...

  6. JWT生成token

    1.JWT简介 JSON Web Token 简称JWT.一个JWT实际上就是一个字符串,它由三部分组成,头部.载荷与签名.JWT生成的token是这样的 2.Json Web Token(JWT)生 ...

  7. .NET6 JWT(生成Token令牌)

    一.Net 6环境下的.net core项目里如何使用JWT. 第一步,在Nuget引入JWT.Microsoft.AspNetCore.Authentication.JwtBearer这两个NuGe ...

  8. JWT生成Token做登录校验

    一.JWT的优点 1.服务端不需要保存传统会话信息,没有跨域传输问题,减小服务器开销. 2.jwt构成简单,占用很少的字节,便于传输. 3.json格式通用,不同语言之间都可以使用. 二.使用JWT进 ...

  9. JSON Web Token (JWT)生成Token及解密实战。

    昨天讲解了JWT的介绍.应用场景.优点及注意事项等,今天来个JWT具体的使用实践吧. 从JWT官网支持的类库来看,jjwt是Java支持的算法中最全的,推荐使用,网址如下. https://githu ...

随机推荐

  1. 两行命令查看自己笔记本连接的wifi密码

    打开cmd.exe窗口 第一行命令 netsh wlan show profiles 可以查看所有曾经连接过的wifi 第二命令 netsh wlan show profiles "vivo ...

  2. vs查找替换功能打不开!

    其实解决办法很简单啊 vs--窗口--重置窗口布局

  3. syncronizationcontext

    FormDesign.cs       增加变量定义  public string testName { get; set; } TaskWrapper.cs string tmpTest = &qu ...

  4. EasyNVR网页摄像机无插件H5、谷歌Chrome直播方案中使用Onvif协议控制视频设备预置位转动

    EasyNVR支持预置位控制,包括转到指定预置位,设置指定预置位,删除指定预置位.预置位在安防领域有较为普遍的应用,可以进行很多既定位置的跳转,很方便.之前我们说过如何用Onvif协议进行设备的发现, ...

  5. Arch Linux 启用 MTU 探测

    最近在家里经常遇到 ssh 超时的问题,一开始也没太当回事,感觉是网络不稳定导致的,但是后来慢慢的发现这种超时问题只会出现在跟 ssh 相关的程序中,例如 git.ssh.这成功的引起了我的注意,于是 ...

  6. IntelliJ IDEA 常用快捷键 之 Windows 版

    IntelliJ IDEA(简称 IDEA),是 Java 语言开发的集成环境,IDEA 在业界被公认为最好的 Java 开发工具之一,尤其在智能代码助手.代码自动提示.重构.J2EE 支持.各类版本 ...

  7. .NET平台历程介绍

    .Net平台的背景 1. 2010之前 的PC时代的时候,互联网规模还不是特别庞大,以静态编译式语言为代表的JAVA和.Net没什么太大区别,.net以windows自居. 2. 2010年以JAVA ...

  8. 01-Windows Server 2012的配置与部署

    一. 背景 这里以阿里云Windows Server 2012系统的服务器为主,介绍服务器的配置以及.Net程序的发布顺序,在后续的项目管理文章中,会介绍<运维手册>的写法. 二. 步骤 ...

  9. Java学习之旅(二):生病的狗1(逻辑推导)

    前言:本篇文章属于个人笔记,例化了一些代码,不知是否合理,请指教. 中午看到一位同学的面试题,觉得很烧脑,烧脑不能一个人烧,要大家一起烧. 村子中有50个人,每人有一条狗.在这50条狗中有病狗(这种病 ...

  10. DELPHI6中DSGNINTF.DCU找不到时的解决方法

    https://www.cnblogs.com/gaodu2003/archive/2009/06/04/1495789.html 1.添加 lib\designide.dcp到控件的dpk文件的re ...