我们在做前后端分离的项目中,最常用的都是使用token认证。

登录后将用户信息,过期时间以及私钥一起加密生成token,但是比较头疼的就是token过期刷新的问题,因为用户在登录后,如果在使用过程中,突然提示token过期了,需要重新登录,会觉得很奇怪。

我使用的方式,是在解析token的时候,如果token过期了,但是还在可刷新的时间范围内,我们应该自动刷新token,并将新的token返回给用户。

但是如果前端采用异步请求,同时发来了多个接口的话,我们不可能对每个请求的token都进行刷新。

我的解决方案是,将过期但还在刷新范围的token存入redis,同时设置token的过期时间为可刷新时间,过了可刷新时间,token就会被自动删除

当前端多个请求过来时,会对请求带来的token进行验证,分三种情况:

  1)如果token已经过了刷新时间,则抛出异常。

  2)如果token不在redis中,表示刚刚过期,还没有进行刷新token操作,需要刷新token。

  3)如果token在redis中,则权限默认通过。

下面上代码:

  1)为了给token加上可刷新时间,需要重写TimedJSONWebSignatureSerializer 的make_header和loads方法

from itsdangerous import TimedJSONWebSignatureSerializer as Serializer_
import redis
r = redis.Redis(host="127.0.0.1", port=6379,db=0)
class Serializer(Serializer_):
def __init__(self, secret_key, expires_in=None, **kwargs):
self.expires_in = expires_in
super(Serializer, self).__init__(secret_key, expires_in, **kwargs) def make_header(self, header_fields):
header = JSONWebSignatureSerializer.make_header(self, header_fields)
iat = self.now()
exp = iat + self.expires_in
refresh_exp = iat+current_app.config["REFRESH_TIME"]
header["iat"] = iat
header["exp"] = exp
header["refresh_exp"] = refresh_exp
return header def loads(self, s, salt=None, return_header=False):
payload, header = JSONWebSignatureSerializer.loads(
self, s, salt, return_header=True
) if "exp" not in header:
raise BadSignature("Missing expiry date", payload=payload) int_date_error = BadHeader("Expiry date is not an IntDate", payload=payload)
try:
header["exp"] = int(header["exp"])
except ValueError:
raise int_date_error
if header["exp"] < 0:
raise int_date_error
now = self.now()
if header["exp"] < now:
if header["refresh_exp"]<now:
# 已经过了可刷新时间,直接抛出异常
raise SignatureExpired(
"Signature expired",
payload=payload,
date_signed=self.get_issue_date(header),
)
else:
# TODO 增加判断,看是否有存储在redis中,如果有存储过,表示token已经被刷新过了,直接放行即可。
if r.get(s):
return payload
pxt = header["refresh_exp"] - now
if pxt>0:
r.set(s, header["exp"], px = pxt)
# 还在可刷新时间内
# 生成新的token返回给前端
serializer = Serializer(current_app.config["SECRET_KEY"], expires_in=self.expires_in)
# 调用serializer的dumps方法将uid和type写入生成token
token = serializer.dumps(payload)
res = make_response()
res.headers["Authorization"] = token
res.set_cookie("authorization",token.decode("ascii"))
return payload, token
if return_header:
return payload, header
return payload 

  2)认证权限

auth = HTTPBasicAuth()
user = namedtuple("User",["uid","type","scope"]) @auth.verify_password
def check_authorization(token, pwd):
user_info = check_auth_token(token)
if not user_info:
return False
else:
if isinstance(user_info, tuple):
user_info_ = user_info[0]
token = user_info[1]
else:
user_info_ = user_info
g.user = user_info_
return True if not token else token def check_auth_token(token):
serialzer = Serializer(current_app.config["SECRET_KEY"])
try:
s = serialzer.loads(token)
except BadSignature:
raise AuthFailed(msg="token is invalid", error_code=1004)
except SignatureExpired:
raise AuthFailed(msg="token is expired", error_code=1004)
token = ""
if isinstance(s, tuple):
u_info = s[0]
token = s[1]
else:
u_info = s
uid = u_info["uid"]
type = u_info["type"]
scope = u_info["scope"]
return user(uid, type, scope), token

  3)生成新的token后,将新的token放入response的header中,前端人员从response header中去取authorization

@api.router("/get/<int:uid>")
@auth.login_required
def get_user(uid, token=None):
user = User.query.get_or_404(uid)
res_json = jsonify(user)
res = make_response(res_json)
res.headers["Authorization"] = token
return res

  

  

flask刷新token的更多相关文章

  1. 十二、存token获取token刷新token发送header头

    //测试token //获取token function setToken(data){ var storage = window.localStorage; if(!storage){ alert( ...

  2. 请求时token过期自动刷新token

    1.在开发过程中,我们都会接触到token,token的作用是什么呢?主要的作用就是为了安全,用户登陆时,服务器会随机生成一个有时效性的token,用户的每一次请求都需要携带上token,证明其请求的 ...

  3. Identity Server 4 原理和实战(完结)_为 MVC 客户端刷新 Token

    服务端修改token的过期使劲为60秒 过期了 仍然还能获取到api1的资源 api1,设置每隔一分钟就验证token 并且要求token必须要有超时时间这个参数, 1分钟后提示超时,两边都是一分钟, ...

  4. ASP.NET Core Web Api之JWT刷新Token(三)

    前言 如题,本节我们进入JWT最后一节内容,JWT本质上就是从身份认证服务器获取访问令牌,继而对于用户后续可访问受保护资源,但是关键问题是:访问令牌的生命周期到底设置成多久呢?见过一些使用JWT的童鞋 ...

  5. SpringBootSecurity学习(20)前后端分离版之OAuth2.0刷新token

    刷新token 前面的例子和配置都是从头开始申请授权码和令牌,现在来看一下如何根据获取令牌时,回参中的 refresh_token 来刷新令牌.现在在项目中配置的是内存模式的默认用户名密码,第一步先改 ...

  6. uni-app 无痛刷新 token 方法

    为了给用户一个流畅的体验, token 过期后需要重新请求新的 token 替换过期的 token 前端在请求接口时,和后端定义好了,如果状态码为 401 ,则表明 token 过期,需要前端请求新的 ...

  7. Vue刷新token,判断token是否过期

    1.判断token是否过期,前端请求后,后台会返回一个状态给你.根据状态判断是否过期,刷新token 2.是否每次请求后端都会返回新的token给你.或者后端给你定义了一个刷新token的方法,那此时 ...

  8. SpringSecurity+Oauth2+Jwt实现toekn认证和刷新token

    简单描述:最近在处理鉴权这一块的东西,需求就是用户登录需要获取token,然后携带token访问接口,token认证成功接口才能返回正确的数据,如果访问接口时候token过期,就采用刷新token刷新 ...

  9. SpringBoot + SpringSecurity + Mybatis-Plus + JWT + Redis 实现分布式系统认证和授权(刷新Token和Token黑名单)

    1. 前提   本文在基于SpringBoot整合SpringSecurity实现JWT的前提中添加刷新Token以及添加Token黑名单.在浏览之前,请查看博客:   SpringBoot + Sp ...

随机推荐

  1. AppBoxFuture(二): Say goodbye to sql!

      信息管理类应用系统离不开关系数据存储,目前大家基本都使用的是传统的数据库如MySql.Postgres等.作者从事信息化建设十多年,个人认为传统的数据库存在以下的问题: 扩展问题:   系统数据的 ...

  2. 权限管理系统之集成Shiro实现登录、url和页面按钮的访问控制

    用户权限管理一般是对用户页面.按钮的访问权限管理.Shiro框架是一个强大且易用的Java安全框架,执行身份验证.授权.密码和会话管理,对于Shiro的介绍这里就不多说.本篇博客主要是了解Shiro的 ...

  3. List<T>常用操作函数

    1.Add():添加单个元素2.AddRange():添加一个集合4.Insert():插入一个元素5.InsertRange():插入一个集合6.Remove():移除指定的元素7.RemoveAt ...

  4. C#委托与事件总结

    目录 C#委托与事件的总结 1.概述 2.委托 2.1 什么是委托 2.2 委託的使用 2.3 深入理解委托 2.4 为什么要使用委托 2.5 代码清单 3.事件 3.1 事件与委托的关系 3.2 订 ...

  5. 图解HTTP(1)之WEB及网络基础

    HTTP协议访问Web 当你在浏览器地址栏中键入有效URL(统一资源定位符)相应的网页页面就会展示出来,那么它是如何展示出来的, 首先这存在两个概念 ------客户端.服务器端 客户端(client ...

  6. [Go] golang结构体成员与函数类型

    package main import ( "fmt" ) //定义一个类型 type tsh struct { //定义成员,类型是func() string test func ...

  7. Java_设计模式之享元模式

    1.关于享元模式 享元模式有点类似于单例模式,都是只生成一个对象被共享使用.享元模式主要目的就是让多个对象实现共享,减少不会要额内存消耗,将多个对同一对象的访问集中起来,不必为每个访问者创建一个单独的 ...

  8. 使用addviewController()实现无业务逻辑跳转

    需要实现WebMvcConfigurer类,重写addViewControllers方法. 添加@Configuration,等价于xml配置. package dbzx.config; import ...

  9. Android 网络框架 Retrofit2

    概述 Retrofit是一个OkHttp网络请求框架的封装库,Retrofit通过注解配置网络参数,可以按照我们的规则去构造实际的HTTP请求,能够灵活设置URL.头部.请求体.返回值等,是目前最优雅 ...

  10. spring学习总结——高级装配学习四(运行时:值注入、spring表达式)

    前言: 当讨论依赖注入的时候,我们通常所讨论的是将一个bean引用注入到另一个bean的属性或构造器参数中.bean装配的另外一个方面指的是将一个值注入到bean的属性或者构造器参数中.在没有学习使用 ...