您的位置:首页 > 其它

8.5 用户注册时发送确认邮件功能——itsdangerous

2018-03-18 17:13 525 查看
__________________________________________________前言________________________________________________________
我们先来看上节的注册视图函数:
@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 db

from itsdangerous import TimedJSONWebSignatureSerializer as Serializer

from flask import current_app

class 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) #生成签名

4000
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 auth

from .forms import RegisterForm

from ..models import User

from .. import db

from ..email import send_mail

from flask import redirect, url_for, flash, render_template

from 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/<token>')

@login_required

def 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.程序提示认证成功并返回主页:



*上面图片的文字介绍都是按照代码的执行顺序来解释的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐