这是albumy/utils.py文件
import os
import uuid
try:
from urlparse import urlparse, urljoin
except ImportError:
from urllib.parse import urlparse, urljoin
import PIL
from PIL import Image
from flask import current_app, request, url_for, redirect, flash
from itsdangerous import BadSignature, SignatureExpired
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from albumy.extensions import db
from albumy.models import User
from albumy.settings import Operations
def generate_token(user, operation, expire_in=None, **kwargs):
s = Serializer(current_app.config['SECRET_KEY'], expire_in)
data = {'id': user.id, 'operation': operation}
data.update(**kwargs)
return s.dumps(data)
def validate_token(user, token, operation, new_password=None):
s = Serializer(current_app.config['SECRET_KEY'])
try:
data = s.loads(token)
except SignatureExpired:
return False
except BadSignature:
return False
if operation != data.get('operation') or user.id != data.get('id'):
return False
if operation == Operations.CONFIRM:
user.confirmed = True
elif operation == Operations.RESET_PASSWORD:
user.set_password(new_password)
elif operation == Operations.CHANGE_EMAIL:
new_email = data.get('new_email')
if new_email is None:
return False
if User.query.filter_by(email=new_email).first() is not None:
return False
user.email = new_email
else:
return False
db.session.commit()
return True
下面是修改email地址时的视图函数:
albumy/blueprints/user.py:
@user_bp.route('/settings/change-email', methods=['GET', 'POST'])
@fresh_login_required
def change_email_request():
form = ChangeEmailForm()
if form.validate_on_submit():
token = generate_token(user=current_user, operation=Operations.CHANGE_EMAIL, new_email=form.email.data.lower())
send_change_email_email(to=form.email.data, user=current_user, token=token)
flash('Confirm email sent, check your inbox.', 'info')
return redirect(url_for('.index', username=current_user.username))
return render_template('user/settings/change_email.html', form=form)
@user_bp.route('/change-email/<token>')
@login_required
def change_email(token):
if validate_token(user=current_user, token=token, operation=Operations.CHANGE_EMAIL):
flash('Email updated.', 'success')
return redirect(url_for('.index', username=current_user.username))
else:
flash('Invalid or expired token.', 'warning')
return redirect(url_for('.change_email_request'))
每次验证,邮件可以发出去,当我点击链接,就提示:Invalid or expired token.
我顺着这个提示,发现验证token时,总是报BadSignature异常。
我又在shell里面进行了验证,如下:
>>> from albumy.utils import generate_token, validate_token
>>> user = User.query.get(1)
>>> operation = 'change-email'
>>> token = generate_token(user=user, operation=operation)
>>> validate_token(user=user, token=token, operation=operation)
False
>>>
这个问题困扰了我一天,也没有解决,而且之前用户确认时也需要进行token认证,之前是可以的,现在也不成功,而且每次从邮箱里面点击链接,都会再发送一封邮件,不知道什么原因。