0


flask使用token认证

前言

原本使用的是session,认证,服务器会把session-id存在浏览器的cookie里面,然后在服务端会保存session-id,也看到很多flask关于session的操作,自定义保存到redis等等,但是在负载均衡的时候,就会发现,当服务器多起来之后,访问的时候其他的服务器并没有保存另一个服务器产生的session-id。当然保存到同一个数据库可以解决,但是我试了一下使用token来认证。
大概思路就是借鉴了这个视频的,可能有很多不符合规范,还请大家多多指出

apifox介绍token的使用

思路

一般token都是放在请求头的Authorization,但是我还是个萌新,项目是使用服务器渲染的,没有做前后端分离,好像没法设置请求头,所以我就观察了一下请求头,发现cookie是每次都会发过来的,所以我就将token存在cookie里面,每次发过来,进行验证,如果能够每次通过验证,就能够保持登录态。

用到的东西

  • flask的钩子函数
  • pyjwt模块

具体实现

token的生成验证

1. 生成token

这个传入的user参数是ORM对象,就是数据库的单个用户的类,具体是这样的:

user = UserModel.query.filter(UserModel.id ==user_id).first()

设置好headers和payload之后,直接使用jwt.encode就可以了,就能得到一个加密的字符串了

defcreate_token(user):
    headers ={"alg":"HS256","typ":"JWT",}
    payload ={"name": user.username,"role": user.role,"user_id": user.id,"exp":int(time.time()+3600),"iss":'cgy'}
    token = jwt.encode(payload=payload, key=current_app.config.get('SECRET_KEY'), algorithm='HS256',
                       headers=headers)return token

2. 验证token

底下可以发现jwt.decode将token解密,可以得到上面写的payload,并且验证issuer。如果验证失败,返回msg,即变量msg不为None,之后也可以根据payload和msg是否为None,进行判断验证是否成功。

defvalidate_token(token):
    payload =None
    msg =Nonetry:
        payload = jwt.decode(jwt=token, key=current_app.config.get('SECRET_KEY'), algorithms=['HS256'], issuer='cgy')except exceptions.ExpiredSignatureError:
        msg ='token已失效'except jwt.DecodeError:
        msg ='token认证失败'except jwt.InvalidTokenError:
        msg ='非法的token'return payload, msg

用户认证流程

在每次接收请求的时候,提取出cookie中的token,然后在每次请求操作结束的时候,生成token,放到cookie中

接收请求时

从cookie中取出token,然后进行认证,如果

@app.before_requestdefbefore_request():
    payload, msg = validate_token(request.cookies.get('token'))if payload isnotNoneand msg isNone:
        user = UserModel.query.filter(UserModel.id== token.get('user_id')).first()
        g.user = user

结束请求时

这个resp是一个响应对象,可以在视图函数中给他绑定一些属性,在这里能够识别到

  • 首先是查看resp这个对象有没有logout这个属性,并且这个属性的值为True,如果是的话,就删除cookie
  • 如果不是退出登录的话,就查看g对象或者resp对象,有没有user这个属性,如果有的话就生成token并且存到cookie中 - g对象:可以看到上面的接收请求的时候,会认证一次,如果能够通过的话,将user存到g对象中,所以这里查看g对象中是否有user这个属性是在检查,这是不是一个登录过的用户的发送请求
@app.after_requestdefafter_request(resp):ifhasattr(resp,'logout')and resp.logout isTrue:
        resp.delete_cookie('token')else:ifhasattr(g,'user'):
            token = create_token(g.user)
            resp.set_cookie('token', token, max_age=3600)return resp

登录赋予登录态

我们会发现一个问题,在接受请求的时候,是先获取到了cookie再给g对象绑定user,这里结束请求的时候再通过在检查g对象中有没有user。我们好像没有在哪里设置g对象有user,从而设置cookie,那么这个所谓的第一次,就在login视图函数里面,可以看到,当使用post请求时,有

g.user = user

,这个第一次,给g对象绑定user,从而结束请求时开始将token加入到cookie中

@bp.route('/login/', methods=['GET','POST'])deflogin():if request.method =='GET':ifhasattr(g,'user'):return redirect('/')return render_template('login.html')elif request.method =='POST':
        form = LoginForm(request.form)if form.validate():
            user = UserModel.query.filter(UserModel.username == form.username.data).first()
            g.user = user
            flash('登录成功')return redirect(url_for('food.index'))else:
            flash('登录失败')return render_template('login.html')

总结

笼统来看就是,
登录的时候,给g对象绑定user,然后在结束那一次请求的时候,会把token加入到cookie中。
在之后接收请求时,会获取cookie中的token并且认证一下,知道这是登录后的用户,再给g对象绑定user
在返回响应前,查看g对象是否有user属性,如果有的话,再更新cookie(因为有时效)

如果想看看网站的话可以访问,http://www.cgy.plus,只是在服务器的pycharm跑着,还没有部署

标签: flask python 后端

本文转载自: https://blog.csdn.net/m0_61143764/article/details/124611058
版权归原作者 gsxdcyy 所有, 如有侵权,请联系我们删除。

“flask使用token认证”的评论:

还没有评论