Flask使用itsdangerous生成令牌
itsdangerous示例
(venv)$python manage.py shell
>>> from manage import app
>>> from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
>>> s = Serializer(app.config['SECRET_KEY'], expires_in = 3600)
>>> token = s.dumps({ 'confirm': 23 })
>>> token
'eyJhbGciOiJIUzI1NiIsImV4cCI6MTM4MTcxODU1OCwiaWF0IjoxMzgxNzE0OTU4fQ.ey ...'
>>> data = s.loads(token)
>>> data
{u'confirm':23}
itsdangerous 提供了多种生成令牌的方法,其中
TimedJSONWebSignatureSerializer
类生成具有过期时间的 JSON Web 签名(JSON Web Signatures,JWS)。这个类的构造函数接收的参数是一个密钥,在 Flask 程序中可使用 SECRET_KEY 设置。dumps() 方法为指定的数据生成一个加密签名,然后再对数据和签名进行序列化,生成令牌字符串。expires_in 参数设置令牌的过期时间,单位为秒。
为了解码令牌,序列化对象提供了 loads() 方法,其唯一的参数是令牌字符串。这个方法
会检验签名和过期时间,如果通过,返回原始数据。如果提供给 loads() 方法的令牌不正
确或过期了,则抛出异常。
实际项目使用流程
本例场景为用户邮箱认证功能。
添加到用户模型类(
models.py
)from itsdangerous import TimedJSONWebSignatureSerializer as Serializer from flask import current_app from . import db class User(UserMixin, db.Model):# ...confirmed = db.Column(db.Boolean, default=False) # 判断用户是否认证,默认False# 生成token令牌def generate_confirmation_token(self, expiration=3600): # 过期时间s = Serializer(current_app.config['SECRET_KEY'], expiration) # 序列化秘钥return s.dumps({'confirm': self.id})# 验证token令牌 def confirm(self, token):s = Serializer(current_app.config['SECRET_KEY']) # 序列化秘钥try:data = s.loads(token) # 验证失败或令牌超时,该方法抛出异常except:return Falseif data.get('confirm') != self.id: # 验证用户id,以防令牌生成方法泄露return Falseself.confirmed = True # 验证通过db.session.add(self) # 保存该用户return True
发送令牌认证邮件(
views.py
)from ..email import send_email # 邮箱验证方法@auth.route('/register', methods = ['GET', 'POST']) def register():form = RegistrationForm()if form.validate_on_submit():# ...db.session.add(user)db.session.commit()token = user.generate_confirmation_token() # 获取认证令牌send_email(user.email, 'Confirm Your Account', 'auth/email/confirm', user=user, token=token) # 发送邮箱,配置模板参数:user、tokenflash('A confirmation email has been sent to you by email.')return redirect(url_for('main.index'))return render_template('auth/register.html', form=form)# 防止邮件丢失,再次发送认证邮件,此时用户为current_user(已登录的用户,即目标用户)。 from flask_login import current_user @auth.route('/confirm') @login_required def resend_confirmation():token = current_user.generate_confirmation_token()send_email(current_user.email, 'Confirm Your Account','auth/email/confirm', user=current_user, token=token)flash('A new confirmation email has been sent to you by email.')return redirect(url_for('main.index'))
用户认证后,验证令牌(
views.py
)from flask.ext.login import current_user@auth.route('/confirm/<token>') @login_required # falsk-login扩展方法,必须先登录,才能调用该方法。 def confirm(token):if current_user.confirmed: # 判断用户是否已经认证return redirect(url_for('main.index'))if current_user.confirm(token): # 用户请求该路由,调用验证函数进行验证。flash('You have confirmed your account. Thanks!') # 成功else:flash('The confirmation link is invalid or has expired.') # 失败return redirect(url_for('main.index'))
- Flask-Login 提供的
login_required
修饰器会保护这个路由,因此,用户点击确认邮件中的链接后,要先登录,然后才能执行这个视图函数。 - 这个函数先检查已登录的用户是否已经确认过,如果确认过,则重定向到首页,因为很显然此时不用做什么操作。这样处理可以避免用户不小心多次点击确认令牌带来额外工作。
- 由于令牌确认完全在 User 模型中完成,所以视图函数只需调用
confirm()
方法即可,然后再根据确认结果显示不同的 Flash 消息。确认成功后,User 模型中confirmed
属性的值会被修改并添加到会话中,请求处理完后,这两个操作被提交到数据库。
- Flask-Login 提供的
当允许未确认的用户登录,但只显示一个页面,这个页面要求用户在获取权限之前先确认账户时,可使用 Flask 提供的 before_request 钩子完成:(
before_request 钩子只能应用到属于该路由的请求上。若想使用针对程序全局请求的钩子,必须使用 before_app_request 装饰器
):@auth.before_app_request def before_request():if current_user.is_authenticated() \and not current_user.confirmed \and request.endpoint[:5] != 'auth.' \and request.endpoint != 'static':return redirect(url_for('auth.unconfirmed'))@auth.route('/unconfirmed') def unconfirmed():if current_user.is_anonymous() or current_user.confirmed:return redirect(url_for('main.index'))return render_template('auth/unconfirmed.html')
同时满足以下 3 个条件时,
before_app_request
处理程序会拦截请求,并且会被重定向到 /auth/unconfirmed 路由,显示一个确认账户相关信息的页面,比如提示绑定手机等。- 用户已登录(current_user.is_authenticated() 必须返回 True)。
- 用户的账户还未确认。
- 请求的端点不在认证路由中。(使用 request.endpoint 获取,访问认证路由要获取权限,因为这些路由的作用是让用户确认账户或执行其他账户管理操作。)
Flask使用itsdangerous生成令牌相关推荐
- OAuth2.0_JWT令牌-生成令牌和校验令牌_Spring Security OAuth2.0认证授权---springcloud工作笔记148
技术交流QQ群[JAVA,C++,Python,.NET,BigData,AI]:170933152 然后我们在我们的微服务中,开始使用这个JWT令牌,首先 我们原来的授权服务中使用的是自己生成的to ...
- 令牌桶生成令牌_使用令牌的经典ASP登录系统
令牌桶生成令牌 This demonstration started out as a follow up to some recently posted questions on the subje ...
- 令牌桶生成令牌_设计令牌如何有效使用令牌
令牌桶生成令牌 "It used to be that designers made an object and walked away. Today the emphasis must s ...
- Lotus API生成令牌
Lotus API生成令牌 获取令牌 权限 默认令牌 本指南说明了如何为Lotus API生成新令牌以及可以为每个令牌附加什么权限. 获取令牌 任何希望与API endpoints(由Lotus No ...
- 使用RSA算法生成令牌
JWT令牌 (1)创建令牌数据 在user-oauth工程中创建测试类com.token.CreateJwtTest,使用它来创建令牌信息,代码如下: public class CreateJwtTe ...
- flask上传图片以及生成缩略图
flask在开发微信公众号或者小程序时会涉及到手机端上传图片以及生成缩略图的需求(注意,一般涉及到图文都是把图片和文字分开储存到两张表中,用外键作为连接) 第一步, 将本地图片上传 1.前端模板: & ...
- Flask celery消息生成消费
Celery 是一个异步任务队列.你可以使用它在你的应用上下文之外执行任务.总的想法就是你的应用程序可能需要执行任何消耗资源的任务都可以交给任务队列,让你的应用程序自由和快速地响应客户端请求. 使用 ...
- python模拟生成steam手机二次验证令牌
最近在尝试着写个steam自动上架交易的程序,结果发现涉及的东西好多- steam登录的时候需要输入手机令牌,手机令牌是动态生成的,每隔30s更新一次,断网的情况下也不会受影响 这种令牌大多是基于TO ...
- python读mongodb很慢_Python3.5+Mongodb+Flask Web实战坑点小结【Dog Plus】
我不是程序员,也不是设计师,我只是碰巧有一些想法和一台电脑. I am not a designer nor a coder. I'm just a guy with a point-of-view ...
最新文章
- 第 21 章 System Utilities 配置工具
- 怪不的软件开发这么挣钱,原来是有这么多职位
- zynq学习01 zynq 单独使用PL模块点亮led
- redux和react-redux的使用详解
- mysql模糊查询不会区分大小写_MySQL模糊查询(like)时区分大小写
- 记事本 换行符_Windows 记事本再度上架 Microsoft Store
- Spring整合Mybatis之注解方式,(注解整合Junit)
- Android四级缓存,RecyclerView的四级缓存-初探
- 把JS和CSS合并到1个文件
- 3D点云模型下载网站
- java绘制雷达图_【带着canvas去流浪(6)】绘制雷达图
- 怎么用c语言利用函数求组合数,C++中求组合数的各种方法总结详解
- linux 下的rpm 和ivh各是什么意思
- 亚马逊服务器443端口开放配置aws
- 崔天翼的找工作总结 zz
- PMP新考纲 敏捷题目 (五)
- NRF24L01的使用
- rhel7配置smba
- 智能家居有必要HomeKit吗?
- c# indexof方法_清单 .IndexOf()方法,以C#为例