flask forum开发笔记(4)登录注册(下)

上一章中还有一个itsdangerous包没有讲,itsdangerous 包可以用来生成包含用户 id 的安全令牌。因为一般来说确认邮件中最简单的确认链接是 http://www.xxx.com/auth/confirm/ 这种形式的URL,其中 id 是数据库分配给用户的数字 id。但是如果被用户识别出了这种格式,那么只需修改id值就可以确认任意的账户,显然这样是违规的。所以这里就需要itsdangerous包来生成一个令牌。

我们可以使用itsdangerous包中的TimedJSONWebSignatureSerializer 类生成具有过期时间的 JSON Web 签名。其中的dumps()方法为指定的数据生成一个加密签名,然后再对数据和签名进行序列化,生成令牌字符串。expires_in参数设置令牌的过期时间,单位为秒。OK,将此功能加入User模型中。

from . import db
from werkzeug.security import generate_password_hash, check_password_hash
from . import login_manager
from flask.ext.login import UserMixin, AnonymousUserMixin
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from flask import current_app

class User(UserMixin, db.Model):
    __tablename__ = 'users'
    ...

    def generate_confirmation_token(self, expiration=3600):
        s = Serializer(current_app.config['SECRET_KEY'], expiration)
        return s.dumps({'confirm': self.id})

    def confirm(self, token):
        s = Serializer(current_app.config['SECRET_KEY'])
        try:
            data = s.loads(token)
        except:
            return False
        if data.get('confirm') != self.id:
            return False
        self.confirmed = True
        db.session.add(self)
        return True

上面出现了一个loads()方法,这个方法会检验签名和过期时间,如果通过,返回原始数据。如果提供给 loads()方法的令牌不正确或过期了,则抛出异常,其唯一的参数是令牌字符串。

接下来需要做发送确认邮件的功能,当前的 /register 路由把新用户添加到数据库中后,会重定向到/index。在重定向之前,这个路由需要发送确认邮件。这个功能参考《Flask Web开发》这本书就可以了,我是拿QQ邮箱作为发送端的,所以我就只讲一下QQ邮箱配置需要注意的地方,在config.py文件中的配置如下。

import os

basedir = os.path.abspath(os.path.dirname(__file__))

class Config:
    ...
    FLASKY_MAIL_SUBJECT_PREFIX = '[DXFORUM]'
    FLASKY_MAIL_SENDER = 'DXFORUM Admin '
    FLASKY_ADMIN = os.environ.get('DXFORUM_ADMIN')
    MAIL_SERVER = 'smtp.qq.com'
    MAIL_PORT = 465
    MAIL_USE_SSL = True
    MAIL_USERNAME = '[email protected]'
    MAIL_PASSWORD = 'XXXXXXXXXXX'
    DEBUG = True

    @staticmethod
    def init_app(app):
        pass

config ={ 'default': Config }

端口号465,MAIL_USERNAME是你的QQ邮箱地址,MAIL_PASSWORD是你QQ邮箱SMTP服务生成的授权码,获取步骤如下:
进入邮箱,点击设置,选择账户

flask forum开发笔记(4)登录注册(下)_第1张图片
72412B61-2199-4EE1-B2E4-3B49381E92CC.png

一直往下拉,找到POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务一栏

flask forum开发笔记(4)登录注册(下)_第2张图片
416E0646-26D8-4F37-9C7A-A88303096AB2.png

只有开启了你的SMTP服务才能成功发送邮件,我这边是已经开启了,然后点击生成授权码,把生成的授权码复制填入MAIL_PASSWORD中即可。当然,MAIL_USERNAMEMAIL_PASSWORD这两个应该在环境配置中配置才更加稳妥,这里只是作为说明写在config.py中。

完成之后运行网站就可以去测试一下自己的注册功能是否成功实现,这里我还踩到一个坑,需要讲清楚。我在用确认邮件来确认注册账户的时候,flash消息提示已经成功验证您的账户,但是数据库中confirmed的值仍然为0,也就是说还是处于未验证状态。后来整了好久发现这个数据根本就没有被提交,应当在User模型中的confirm方法中添加db.session.commit()方法。

但是书中并没有写,这是因为它在配置文件中配置时写了SQLALCHEMY_COMMIT_ON_TEARDOWN = True这个配置键,这个配置键的作用我在第二章写过,是用于每次request自动提交db.session.commit(),而且我还写了这个配置键在最新版的Flask-SQLAlchemy中这个配置键已经被移除了,无需配置。Flask-SQLAlchemy 的 Changelog 文档里可以看出确实被移除了。

flask forum开发笔记(4)登录注册(下)_第3张图片
1DE0247F-153D-4AFB-9088-8997BA5D25CB.png

在查看完我的Flask-SQLAlchemy版本确认是最新版的之后,现在我只能说,它只是从文档中移除了,而没有从代码中移除,所以还是可以配置使用的。为了方便起见,我还是选择配置了,当然也可以自己去多加一个db.session.commit()方法,这无关紧要。

你可能感兴趣的:(flask forum开发笔记(4)登录注册(下))