当前位置:网站首页>flask实现强制登陆
flask实现强制登陆
2022-07-06 09:24:00 【小白阿远】
为什么要使用强制登陆
这已经是一个APP要走的常规路线了,你不登录的话,开发商平台,就不好对你进行大数据分析了,他们就不能根据你的爱好给你推送你喜欢的内容了(非绝对),或者是某些功能在未登陆的时候无法使用,举个例子:
假如你经常用一个APP,你今天用苹果手机看的,中午又用平板电脑看了会,去外面又拿着朋友手机看了会。
这个场景下,假如你不登录,平台就不知道这几个行为都是同一个人看的,要是APP要求你必须登录,那么这几次都用同一个账号,他就知道都是你一个人换了好几个设备在看了。
好了,有了这个前提,那么接下来围绕你这个账号就能做很多事了,不管你怎么换设备,账号通用,你喜欢看美食,你喜欢看美女等等,全都给你标记在后台。
后来某一天,你会发现,昨天刚跟你聚餐的朋友才跟你显摆过一件新买的衣服,你的这个某某APP就弹出来同款链接广告了。
此时,你的疑问大于看到同款的巧合,这到底是怎么回事????
究其原因,就是因为每个APP都需要登录,都需要定位,都需要各种权限,然后你周围的人跟你很多因素高度重合之后,就有了这些奇妙的巧合。
判断一个用户是否登录是通过判断用户是否携带token,因此登陆前要先生成token,并在登陆的时候将token携带过去flask中生成token可以通过一下方式例:
封装一个生成token的方法在登陆的时候调用生成token,部分参数的意思可以参照代码中对应的注释进行理解,此处生成token的方法使用了jwt中的encode方法,并设置有过期时间,具体过期时间可以根据自身需求设置,此处加密算法使用HS256进行加密
注意由于日期格式不可进行序列化因此需要将日期格式数据转换为字符串格式的数据
我们需要先给他传一个SECRET_KEY,这个SECRET_KEY可以是随意的字符串
def generate_token(payload, expiry, secret=None, algorithm='HS256'): """ :param payload: dict 载荷,用户信息 :param expiry: date 有效期 :param secret: 每个项目的私钥, 要在配置文件中存放 :param algorithm: 加密算法 :return: token """ # 私有变量,不对外提供 # 生成有效期 _payload = { 'expiry': str(expiry) # 日期格式不能进行序列化 } try: _payload.update(payload) if not secret: # 从配置文件的对象中读取 secret = current_app.config.get('SECRET_KEY') # 把生成的token进行拼接,然后写入请求头 token = jwt.encode(payload=_payload, key=secret,algorithm=algorithm) return token except Exception as e: error = traceback.format_exc() print('生成token 错误 :{}'.format(error))
生成token之后一定要进行校验否则可能因为token自身的原因导致登陆失败或者无法进行其他的操作,这里使用的token的解码方世一定要和生成token的加密方式相对应,由于生成token的方式为jwt中的encode,因此解码时就是用jwt中的docode进行解码处理,解码之后进行校验判断是否一致,并且要注意token是否过期,每个token都设置有过期时间,如若过期也将出现token不一致的情况,并且注意解密时加密算法必须与生成的一致,以此为例使用HS256
def verify_token(token,secret=None,algorithm='HS256'):
"""
校验token
:param token: 传递来的token
:param secret: 每个项目的私钥, 要在配置文件中存放
:param algorithm: 加密算法
:return: payload 用户信息部分
"""
if not secret:
# 从配置文件中读取SECRET_KEY
secret = current_app.config.get('SECRET_KEY')
try:
payload = jwt.decode(token, secret, algorithms=algorithm)
except Exception as e:
print("解密错误信息>>>", e)
payload = None
return payload
由于token设置有过期时间需要用户定时登录,否则就需要重新登录,为了方便用户的使用,我们可以实现自动刷新token,所谓自动刷新token即设置一个较长过期时间的token,因为不论token过期时间长短都携带有用户信息,因此我们可以在过期时间较短的token过期时,使用较长过期时间的token中的用户信息重新生成一个token,以此来实现token的自动刷新,大大优化了用户的使用体验,代码如下(仅供参考)
def _generate_token(account,user_id, refresh=True):
"""
生成token 和 刷新token
:return: token, refresh_token
"""
secret = current_app.config.get('SECRET_KEY')
# 定义过期时间: 2小时有效期
expiry = datetime.utcnow() + timedelta(hours=2)
# 生成Token
token = 'Bearer ' + generate_token({'account': account, 'user_id': user_id}, expiry, secret).decode()
if refresh:
# 生成新token, 无感知刷新
expiry = datetime.utcnow() + timedelta(days=15)
# is_refresh作为更新token的信号
refresh_token = 'Bearer ' + generate_token({'account': account, 'user_id': user_id, 'is_refresh': True}, expiry, secret).decode()
else:
refresh_token = None
return token, refresh_token
加密方式与解密方世同上所诉
token的生成与校验就是以上这些内容
登陆的时候携带token
可以根据需求传入需要的字段以及token和自动刷新的token,中间可以打印一下查看是否获取到了token,以此还可以在出错的时候快速定位出错的地方
user_id = user.id
token, refresh_token = _generate_token(account=account, user_id=user.id)
print('登陆的token', token)
data = {
'message': 'login success',
'data': {'code': 200, 'token': token, 'refresh': refresh_token,
'account': account, 'id': user.id, 'uid': user_id}
}
return data
强制登陆的实现
def login_required(func):
"""强制登录装饰器"""
# wraps 是返回装饰器,参数是传来的函数,
@wraps(func)
def wrapper(*args, **kwargs):
print("func的名字是>>", func.__name__)
if g.user_id is not None:
print(g.user_id)
return func(*args, **kwargs)
return {'code': 401, 'message': '无效token 账号为空'}
return wrapper
flask中的g对象是专门⽤来保存⽤户的数据的。我们可以理解这个g对象是⼀个全局的对象,这个对象存储的是我们某⼀次请求的所有的信息,g 作为 flask 程序全局的⼀个临时变量,充当者中间媒介的作⽤,我们可以通过它传递⼀些数据,g 保存的是当前请求的全局变量
因此我么可以从g对象中取出我们请求中传进去的用户id,通过用户id是否为空判断token是否为空,来保证用户的登陆的时候出现因token出现的错误
强制登录就是为了防止项目中的某些功能在未登录的情况下无法使用来实现的,我们可以将强制登陆写在一个装饰器里边,这样不仅减少了代码量,避免代码看起来冗余,而且还方便使用,哪里需要装饰器直接调用即可
装饰器的调用也十分的简单,@+我们定义的装饰器的名字,即可调用
装饰器的名字可以随意写,但是为了使我们的代码简单明了,命名时尽量做到见名识意
@login_required
以此为例 就可以实现flask实现强制登陆,希望可以对您有所帮助
边栏推荐
- Intranet information collection of Intranet penetration (3)
- 《英特尔 oneAPI—打开异构新纪元》
- Harmonyos JS demo application development
- Lintcode logo queries the two nearest saplings
- JDBC read this article is enough
- Experiment 4 array
- Which is more advantageous in short-term or long-term spot gold investment?
- {1,2,3,2,5}查重问题
- Tencent map circle
- Realize applet payment function with applet cloud development (including source code)
猜你喜欢
Experiment 6 inheritance and polymorphism
《统计学》第八版贾俊平第四章总结及课后习题答案
HackMyvm靶机系列(3)-visions
"Gold, silver and four" job hopping needs to be cautious. Can an article solve the interview?
《统计学》第八版贾俊平第六章统计量及抽样分布知识点总结及课后习题答案
HackMyvm靶机系列(4)-vulny
搭建域环境(win)
[paper reproduction] cyclegan (based on pytorch framework) {unfinished}
《统计学》第八版贾俊平第五章概率与概率分布
循环队列(C语言)
随机推荐
Experiment 7 use of common classes (correction post)
7-11 mechanic mustadio (PTA program design)
xray與burp聯動 挖掘
浅谈漏洞发现思路
Wu Enda's latest interview! Data centric reasons
Tencent map circle
记一次edu,SQL注入实战
How to earn the first pot of gold in CSDN (we are all creators)
JDBC看这篇就够了
XSS之冷门事件
Uibutton status exploration and customization
7-6 local minimum of matrix (PTA program design)
Attack and defense world misc practice area (GIF lift table ext3)
HackMyvm靶机系列(7)-Tron
[VMware abnormal problems] problem analysis & Solutions
DVWA (5th week)
Statistics 8th Edition Jia Junping Chapter 7 Summary of knowledge points and answers to exercises after class
Sentinel overall workflow
JDBC transactions, batch processing, and connection pooling (super detailed)
How does SQLite count the data that meets another condition under the data that has been classified once