解决Flask Web request.args.get('next')问题
1、问题再现:
目标实现的功能:当用户注册后,程序自动发送用于确认邮箱的连接到注册邮箱上,当用户点出确认链接后,转到登陆页面,用户输入登陆信息后达到自动确认邮箱的目的
1. 创建登陆表单
<form action="auth.login" method='POST'>
...
</form>
2. 在User模型中添加生成token及验证token的方法
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
def gernerate_token(self):
s = Serializer(SECRET_KEY)
token = s.dumps({'confirm':self.id})
return token
def confirm_token(self, token):
s = Serializer(SECRET_KEY)
try:
data = s.loads(token)
if data.get('confirm') != self.id:
return False
else:
self.confirmed=True
db.session.add(self)
db.session.commit()
return True
3.在登陆路由上的配置
@auth.route('auth.login')
def login():
form = loginForm()
if form.validate_on_submit():
user = User.query.filter_by(username=form.email.data).first()
if user is not None and user.verify_pass(form.password.data):
login_user(user)
return redirect(request.args.get('next') or url_for('main.index'))
return redirect(url_for('main.index'))
4. 在验证令牌路由上的配置
@auth.route('/confirm/<token>')
@login_required
def confirm(token):
if current_user.confirmed:
flash('邮箱已经确认!')
return redirect(url_for('main.index'))
else:
if user.confirm_token(token):
flash('恭喜!邮箱确认成功!')
else:
flash('令牌错误或者过期!')
return redirect('main.index')
2、按照以上步骤设置,令牌生成及发送功能已没有问题,唯独令牌验证上出现了问题。主要问题在于在登陆页面跳转时request.args.get('next')总是返回None, 这就使得用户登陆后无法实现邮箱确认的功能
3、解决方案:
1. 问题是如何引起的:
当用户提交表单后,表单中定义了处理表单数据的路由'auth.login',所以每次提交数据,都将跳转到auth/login这个连接去,而这链接中没有'next'这个参数,这就是为什么request.args.get('next') 总是返回None的原因。
2. 解决问题的方案:
修改登陆表单中的路由,去掉或者改为空action=''。这样修改后,邮箱验证的功能就正常了。