博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
8.5 用户注册时发送确认邮件功能——itsdangerous
阅读量:4095 次
发布时间:2019-05-25

本文共 4252 字,大约阅读时间需要 14 分钟。

__________________________________________________前言________________________________________________________

我们先来看上节的注册视图函数:

@auth.route('/register', methods=['GET', 'POST'])    def register():        form = RegisterForm()  #创建表单        if form.validate_on_submit():  #填写的表单数据通过验证函数            u = User(email=form.email.data, username=form.username.data, password=form.password.data)  #创建用户            db.session.commit(u)  #把用户添加到会话            flash('You can now login.')  #提示用户已经可以登录            return redirect(url_for('auth.login'))  #重定向        return render_template('auth/register.html', form=form)

    用户填写完注册表单点击提交按钮后, 会通过validate_on_submit验证, 然后创建该用户, 把该用户提交到会话。

    但此处存在一个问题, 我们不知道用户输入的email是不是有效的email, 我们到底能不能通过该email联系上用户, 所以我们要添加一个发送确认邮件的功能, 思路如下:

      1.用户注册以后, 我们先提交会话, 因为id是数据库分配的, 只有提交会话以后用户才有id;

      2.向用户发送一封确认邮件, 该邮件的主要内容是一含有用户id的确认链接,该链接映射确认函数;

      3.用户打开邮箱点击确认链接, 视图函数处理用户请求, 先要求用户登录——login_required,然后对照登录用户的id是否和链接中的id相同, 如果相同, 则验证成功, 把用户的confirm字段改为True。

————————————————————————————————————————————————————

    以上就是我们的思路, 但是考虑还不够周到:

     用户id比较容易猜测, 如果恶意用户知道了链接格式, 便可轻松确认任何用户, 所以我们要对用户id进行加密, 借助itsdangerous包把用户id加密成token字符串;

    在发送邮件之前生成token字符串, 点击链接之后验证token字符串就好了。

下面对我们的程序进行修改:

——————————————————————分界线——————————————————————————

一. 修改|-app/models.py

token是由用户id生成的, 验证的时候用户id是由token解密得到的, 所以生成token和验证token的函数应该放到User表中:

from . import dbfrom itsdangerous import TimedJSONWebSignatureSerializer as Serializerfrom flask import current_appclass User(db.Model):    #...    confirm = db.Column(db.Boolean, default=False)  #添加验证字段    def generate_token(self, expiration=3600):        s = Serializer(current_app.config['SECRET_KEY'], expires_in=expiration)  #生成签名        return s.dumps({'confirm': self.id})  #返回加密后的token字符串    def confirm_token(self, token):        s = Serializer(current_app.config['SECRET_KEY'])        try:            data = s.loads(token)  #解密token, 得到id字典        except:             return False         if data.get('confirm') != self.id:  #如果token中的id不等于当前用户id, 验证失败             return False         self.confirm = True  #修改该用户的confirm字段         db.session.add(user)  #把用户添加到会话里         return True

*我们在User表中新加了confirm属性, 需要我们重新生成迁移脚本, 并把迁移应用到数据库中, 我们在前面的章节已经有介绍怎么做, 此处不再赘述。

二. 修改|-app/-auth/views.py

我们需要在注册视图里添加发送邮件的功能, 然后新增加一个确认路由:

from . import authfrom .forms import RegisterFormfrom ..models import Userfrom .. import dbfrom ..email import send_mailfrom flask import redirect, url_for, flash, render_templatefrom flask_login import login_required@auth.route('/register', methods=['GET', 'POST'])def register():    form = RegisterForm()  #注册表单    if form.validate_on_submit():  #用户提交的表单数据通过验证函数时为True        user = User(email=form.email.data, username=form.username.data, password=form.password.data)        db.session.add(user)        db.session.commit()  #把会话提交到数据库中后用户才有id        token = user.generate_token()  #生成token字符串        send_mail(user.email, 'Confirm your account', 'auth/email/confirm',  user=user, token=token)  #向用户发确认邮件        flash('a confirm email has been sent to your email.')        return redirect(urll_for('main.index'))     return render_template('auth/register', form=form)@auth.route('/confirm/
')@login_requireddef confirm(token): if current_user.confirm: return redirect(url_for('main.index')) #防止用户重复点击验证链接 if current_user.confirm_token(token): #无论验证成功与否, 都先提示用户然后返回主页 flash('You have confirmed your account successfully.') else: flash('Confirm failed.') return redirect(url_for('main.index'))

三. 修改|-app/templates/auth/email/confirm.txt

Dear  {
{ user.username }}Please click the link below to confirm your account:{
{ url_for('auth.confirm', token=token, _external=True) }}

confirm.html与.txt文件类似, 不再赘述。

*url_for生成的是相对地址, 只能用在程序网页的上下文中, 在邮箱中需要绝对地址, 所以把_external参数设置为True。

四. 效果演示

1.填写注册信息

2.我们点击提交以后, 发送post请求到register视图函数, 创建用户并提交到数据库:

3.发送邮件, 显示提示信息, 并重定向到主页:

4.打开邮箱, 发现有一封新邮件:

5.点击邮件的链接, 因为confirm视图函数有@login_required修饰器, 没有登陆也就没有得到访问该函数的授权,所以会重定向到登录页面:

6.填写完登录信息后, 点击提交按钮,

这时由auth.login视图函数处理post请求, login函数在验证完用户密码后返回重定向, 代码是——return redirect(request.args.get('next'or url_for('main.index')), 第一个参数的作用是存储上次用户访问的未授权的url, 也就是被login_required阻止访问的验证函数的url, 重新访问confirm函数, 通过验证, 数据库中用户的confirm字段被修改为1:

7.程序提示认证成功并返回主页:

*上面图片的文字介绍都是按照代码的执行顺序来解释的。

你可能感兴趣的文章
Spring Boot构建简单的微博应用
查看>>
Spring处理表单提交
查看>>
Spring MVC异常处理
查看>>
Leetcode 1180. Count Substrings with Only One Distinct Letter [Python]
查看>>
PHP 7 的五大新特性
查看>>
php使用 memcache 来存储 session
查看>>
php实现socket(转)
查看>>
PHP底层的运行机制与原理
查看>>
深入了解php底层机制
查看>>
PHP中的stdClass 【转】
查看>>
XHProf-php轻量级的性能分析工具
查看>>
PHP7新特性 What will be in PHP 7/PHPNG
查看>>
比较strtr, str_replace和preg_replace三个函数的效率
查看>>
ubuntu 下编译PHP5.5.7问题:configure: error: freetype.h not found.
查看>>
PHP编译configure时常见错误 debian centos
查看>>
configure: error: Please reinstall the BZip2 distribution
查看>>
OpenCV gpu模块样例注释:video_reader.cpp
查看>>
【增强学习在无人驾驶中的应用】
查看>>
《python+opencv实践》四、图像特征提取与描述——29理解图像特征
查看>>
《python+opencv实践》四、图像特征提取与描述——30Harris 角点检测
查看>>