使用redis存储用户密码修改验证码

2020-10-19 10:04:21 Python 209

简介

我们不管在什么网站上进行用户信息修改或者登录的时候,都需要提供验证码,而且这个验证码是有有效时间的,那么它到底是怎么是实现的呢?本文通过redis的方案,来比较简单快捷的实现这一个功能。

redis是什么

REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统。

Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Hash), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型。

详细关于redis的介绍可以去看这里:https://www.runoob.com/redis/redis-tutorial.html

Python使用redis

安装 redis 模块

在python中,如果需要操作redis,那么需要先安装相应的第三方模块,在这里我使用的是python-redis,可以使用下面的命令进行安装。

pip install python-redis

测试是否安装成功

>>>python
>>>import redis

如果没有报错,则说明redis安装成功。

简单的python操作redis

redis 提供两个类 RedisStrictRedis, StrictRedis 用于实现大部分官方的命令,Redis 是 StrictRedis 的子类,用于向后兼用旧版本。

redis 取出的结果默认是字节,我们可以设定 decode_responses=True 改成字符串。

import redis   

r = redis.Redis(host='localhost', port=6379, decode_responses=True)  
r.set('name', 'runoob')  # 设置 name 对应的值
print(r['name'])
print(r.get('name'))  # 取出键 name 对应的值
print(type(r.get('name')))  # 查看类型

输入结果:

runoob
runoob
<class 'str'>

使用redis存储、验证验证码

有了上述的先行知识,我们就可以使用redis存储验证码,进行相关的业务逻辑操作了。用户重置密码的流程如下图所示。

重置密码流程

使用redis存储验证码

在用户开始了密码重置操作,我们需要将验证码发送到用户的注册邮箱中,此时,redis也应该保存该验证码,并且设置一个过期时间,操作此段时间后,验证码就失效了。代码如下所示:

# extension.py
import redis
# 使用连接池的方式连接,提高系统性能
pool = redis.ConnectionPool(host='localhost', port=6379, decode_responses=True)
rd = redis.Redis(connection_pool=pool)


# auth.py
@auth_bp.route('/password-reset/', methods=['GET', 'POST'])
def reset_password():
    email = request.form.get('email')
    user = User.query.filter_by(email=email).first()
    if not user:
        flash('邮箱不存在,请输入正确的邮箱!', 'danger')
        return redirect(url_for('.forget_pwd'))
    ver_code = generate_ver_code()
    # 将验证码设置到redis中,过期时间为10分钟
    rd.set(user.id, ver_code, ex=current_app.config['EXPIRE_TIME'])
    token = generate_token(user=user, operation=Operations.RESET_PASSWORD)
    send_reset_password_email(user=user, token=token, ver_code=ver_code)
    flash('验证邮件发送成功,请到邮箱查看然后重置密码!', 'success')
    return render_template('main/auth/pwdResetNext.html')

使用redis验证验证码

在完成上面的操作之后,用户的邮箱会收到一个邮件,里面包含有重置密码的连接以及验证码。之后我们就可以使用redis来验证验证码了,代码如下。

@auth_bp.route('/reset-confirm/', methods=['POST', 'GET'])
def reset_confirm():
    if current_user.is_authenticated:
        return redirect(url_for('.login'))

    form = ResetPwdForm()
    if form.validate_on_submit():
        email = form.email.data
        usr = User.query.filter_by(email=email).first()
        # 如果输入的邮箱不存在
        if not usr:
            flash('邮箱不存在,请输入正确的邮箱~', 'danger')
            return render_template('main/auth/resetPwd.html', form=form)
        # 如果验证码已经超出了有效时间
        if rd.get(usr.id) is None:
            flash('验证码已过期.', 'danger')
            return render_template('main/auth/resetPwd.html', form=form)
        pwd= form.confirm_pwd.data
        ver_code = form.ver_code.data

        # 如果输入的验证码与redis中的不一致
        if ver_code != rd.get(usr.id):
            flash('验证码错误')
            return render_template('main/auth/resetPwd.html', form=form)
        usr.set_password(pwd)
        db.session.commit()
        flash('密码重置成功!', 'success')
        return redirect(url_for('.login'))
    return render_template('main/auth/resetPwd.html', form=form)

在上面的代码中,我们可以通过rd.get(usr.id)来获取当前用户的验证码,同时如果用户重复操作,验证码会自动替换成最新的验证码,如果验证码过期,那么通过rd.get(usr.id)的值将会为空。

至此,一个简单的验证码验证就完成了。当然如果真要用在大型项目上,那么不仅仅是这么简单的操作,需要考虑到的东西十分多!!!

同时,redis的功能不仅于此,想想一个场景,在关系数据库中,例如MySQL,如果一张表中的数据变化频率非常的小,同时表中的数据又十分的多了,如果每次访问该表都去进行查询的话,如果数据库优化做的好,那么查询速度还是可观,如果像我这种数据库渣渣的话,那么查询时间肯定又长又臭了。因此我们可以将更新频率不高的数据放入redis缓存中去,毕竟别人是内存性数据库,这数据不是你MySQL能比拟的,但是也需要注意以下几点

  1. 数据一致性,即缓存数据库中数据应该与MySQL中保持一致,不能出现数据滞后更新等状态
  2. 不要缓存那些对数据一致性要求很高的数据

上述代码都是个人博客网站的代码片段,如果需要看到效果,可以前往Blogin源代码

您尚未登录, 登录注册 后评论

当前共有1条评论


清水 博主

写的不错啊 小伙子