1. 重置密码的一些知识
我们设计重置密码的时候,一般是发送一个重置密码的邮件到客户。邮件中一般包含用户信息来标识用户,标识用户一般有三种方法。
方法一:URL中附带用户ID
直接在邮件中附带用户ID会暴露用户ID,容易被篡改成其他用户ID
方法二:服务端加密用户ID
通过服务端加密然后附带到邮件,可以有效防止暴露ID
方法三:服务器缓存键值对
通过在服务器端缓存一个键值对,key为一串随机字符串,Value为用户ID
方法二和三均要设置过期时间。
2. first_or_404
当我们进行查询的时候可以使用first
或者first_or_404
。两者的区别是first
查询不到的时候返回的是None
,first_or_404
是直接抛出异常(404 Not Found)不再执行下面的代码。
first_or_404
实现了对first
的封装,当不存在的时候直接由Abort
抛出异常,异常类属于HttpException
。
下面我们看下源码:
1 | class BaseQuery(orm.Query): |
我们看到当查找为空的之后,会调用abort
。
1 | def abort(status, *args, **kwargs): |
我们看到abort
方法内部只是调用了一个类。这个类当成了方法一样使用,这是因为类的内部实现了__call__
方法。
1 | class Aborter(object): |
一旦我们在类中实现了魔法方法__call__
那么我们可以向方法一样使用类。这种可以直接当成函数一样调用的对象我们称之为可调用对象。
可调用对象
上面我们说了主要实现了魔法方法__call__
的对象就是可调用对象。那可调用对象有哪些作用呢?
作用一:简化对象下方法的调用
假设我们一个对象下有一个函数,我们需要使用a.func()
的方式调用,但是当我们写成可调用对象的时候可以直接使用a()
的方式调用。
在哪些情况下可以将一个对象实现为可调用对象呢?
- 当对象下只有一个方法的时候(构造函数不算)
- 对象下某个方法使用很多的时候
作用二:模糊了函数和对象的区别
我们使用可调用对象就像使用函数一样a()
和func()
。意义在于统一调用接口。
我们接着看源码
1 | raise self.mapping[code](*args, **kwargs) |
这里的mapping
代表什么呢?
1 | mapping = default_exceptions |
我们看到初始化方法中将default_exceptions
赋值给了mapping
。
1 | default_exceptions = {} |
上面的操作就是讲同一个文件下所有的HTTPException
子类加到default_exceptions
。
最终first_or_404
返回的是HTTPException
的子类。那具体是哪一个子类呢?
我们可以根据状态码来找到(default_exceptions
存的就是根据状态码找到异常类)
1 | class NotFound(HTTPException): |
其实HTTPException
也是一个可调用对象
1 | return _aborter(status, *args, **kwargs) |
正是这段代码使在出现异常的之后直接返回前端错误页面,而不是继续执行代码。
装饰器app_errorhandler
first_or_404
会抛出一个404
的错误,我们如果在抛出的地方去捕捉,将会有很多冗余代码,我们可以写一个全局的异常处理,指定错误代码。
1 |
|
上面的代码会拦截所有的404
异常代码,然后返回我们自定义的错误页面。
上面的代码我们可以编写更多的逻辑,如:记录错误日志,返回指定的字符串等。
3. 发送邮件
这里是使用flask-mail
进行电子邮件的发送。
安装
1 | pip install flask-mail |
注册实例化
1 | from flask_mail import Mail |
配置
1 | # Email 配置 |
Flask-mail文档:http://www.pythondoc.com/flask-mail/
4. 使用itsdangerous生成令牌
我们重置密码的策略是将用户ID加密后发送到用户邮件,这里使用itsdangerous
进行加密处理
1 | from itsdangerous import TimedJSONWebSignatureSerializer as Serializer |
这里我们可以放任何的信息在里面
接着我们要写一个校验token
正确与否的函数
1 | def confirm(self, token): |