Python 通过其危险令牌获取用户信息
我目前正在通过米格尔·格林伯格的书学习烧瓶。如果您熟悉,您可能知道(Miguel在本书中使用的应用程序) 我现在在第8节,处理密码重置,这里是原始代码(你也可以在回购协议上找到它。它的标签是8g): 型号.pyPython 通过其危险令牌获取用户信息,python,flask,token,Python,Flask,Token,我目前正在通过米格尔·格林伯格的书学习烧瓶。如果您熟悉,您可能知道(Miguel在本书中使用的应用程序) 我现在在第8节,处理密码重置,这里是原始代码(你也可以在回购协议上找到它。它的标签是8g): 型号.py class User(UserMixin, db.Model): __tablename__ = 'users' ... def generate_reset_token(self, expiration=3600): s = Serializer
class User(UserMixin, db.Model):
__tablename__ = 'users'
...
def generate_reset_token(self, expiration=3600):
s = Serializer(current_app.config['SECRET_KEY'], expiration)
return s.dumps({'reset': self.id})
def reset_password(self, token, new_password):
s = Serializer(current_app.config['SECRET_KEY'])
try:
data = s.loads(token)
except:
return False
if data.get('reset') != self.id:
return False
self.password = new_password
db.session.add(self)
return True
@auth.route('/reset/<token>', methods=['GET', 'POST'])
def password_reset(token):
if not current_user.is_anonymous:
return redirect(url_for('main.index'))
form = PasswordResetForm()
if form.validate_on_submit():
user = User.query.filter_by(email=form.email.data).first()
if user is None:
return redirect(url_for('main.index'))
if user.reset_password(token, form.password.data):
flash('Your password has been updated.')
return redirect(url_for('auth.login'))
else:
return redirect(url_for('main.index'))
return render_template('auth/reset_password.html', form=form)
class PasswordResetForm(Form):
email = StringField('Email', validators=[Required(), Length(1, 64),
Email()])
password = PasswordField('New Password', validators=[
Required(), EqualTo('password2', message='Passwords must match')])
password2 = PasswordField('Confirm password', validators=[Required()])
submit = SubmitField('Reset Password')
def validate_email(self, field):
if User.query.filter_by(email=field.data).first() is None:
raise ValidationError('Unknown email address.')
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
@auth.route('/reset/<token>', methods=['GET', 'POST'])
def reset_password(token):
s = Serializer(current_app.config['SECRET_KEY'])
try:
data = s.loads(token)
except:
raise ValidationError()
user_id = data['reset']
....
class User(UserMixin, db.Model):
__tablename__ = 'users'
...
def reset_password(self, new_password):
self.password = new_password
db.session.add(self)
return True
auth/views.py
class User(UserMixin, db.Model):
__tablename__ = 'users'
...
def generate_reset_token(self, expiration=3600):
s = Serializer(current_app.config['SECRET_KEY'], expiration)
return s.dumps({'reset': self.id})
def reset_password(self, token, new_password):
s = Serializer(current_app.config['SECRET_KEY'])
try:
data = s.loads(token)
except:
return False
if data.get('reset') != self.id:
return False
self.password = new_password
db.session.add(self)
return True
@auth.route('/reset/<token>', methods=['GET', 'POST'])
def password_reset(token):
if not current_user.is_anonymous:
return redirect(url_for('main.index'))
form = PasswordResetForm()
if form.validate_on_submit():
user = User.query.filter_by(email=form.email.data).first()
if user is None:
return redirect(url_for('main.index'))
if user.reset_password(token, form.password.data):
flash('Your password has been updated.')
return redirect(url_for('auth.login'))
else:
return redirect(url_for('main.index'))
return render_template('auth/reset_password.html', form=form)
class PasswordResetForm(Form):
email = StringField('Email', validators=[Required(), Length(1, 64),
Email()])
password = PasswordField('New Password', validators=[
Required(), EqualTo('password2', message='Passwords must match')])
password2 = PasswordField('Confirm password', validators=[Required()])
submit = SubmitField('Reset Password')
def validate_email(self, field):
if User.query.filter_by(email=field.data).first() is None:
raise ValidationError('Unknown email address.')
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
@auth.route('/reset/<token>', methods=['GET', 'POST'])
def reset_password(token):
s = Serializer(current_app.config['SECRET_KEY'])
try:
data = s.loads(token)
except:
raise ValidationError()
user_id = data['reset']
....
class User(UserMixin, db.Model):
__tablename__ = 'users'
...
def reset_password(self, new_password):
self.password = new_password
db.session.add(self)
return True
我的问题:
我不想再次向用户索要他们的电子邮件,因为他们正在通过收到的电子邮件更改密码。有没有办法从该令牌获取用户或用户的电子邮件 对于1-在安全级别上,隐藏在您网站上拥有帐户的用户可能是一个很好的优势。例如,假设这是一个瘾君子匿名网站,如果我想看看
alice@example.com
如果她是会员,我可以尝试重置密码以确认她是会员
或者,如果您有大量电子邮件地址,您可以使用密码重置表单将列表缩小到活动成员,以便在更有针对性的社会工程攻击中使用,或者至少缩小列表(如果您的目标是暴力攻击他们)。好的,以防这对其他人有用。用户信息已经在{'reset':user_id}中的令牌中 问题在于令牌管理逻辑在用户模型中。因此,在表单中有一个电子邮件字段,以便以后在视图中查找该用户,在当前版本中就可以做到这一点 由于您在该视图中获得了令牌,因此我们可以将该逻辑移动到该视图: auth/views.py
class User(UserMixin, db.Model):
__tablename__ = 'users'
...
def generate_reset_token(self, expiration=3600):
s = Serializer(current_app.config['SECRET_KEY'], expiration)
return s.dumps({'reset': self.id})
def reset_password(self, token, new_password):
s = Serializer(current_app.config['SECRET_KEY'])
try:
data = s.loads(token)
except:
return False
if data.get('reset') != self.id:
return False
self.password = new_password
db.session.add(self)
return True
@auth.route('/reset/<token>', methods=['GET', 'POST'])
def password_reset(token):
if not current_user.is_anonymous:
return redirect(url_for('main.index'))
form = PasswordResetForm()
if form.validate_on_submit():
user = User.query.filter_by(email=form.email.data).first()
if user is None:
return redirect(url_for('main.index'))
if user.reset_password(token, form.password.data):
flash('Your password has been updated.')
return redirect(url_for('auth.login'))
else:
return redirect(url_for('main.index'))
return render_template('auth/reset_password.html', form=form)
class PasswordResetForm(Form):
email = StringField('Email', validators=[Required(), Length(1, 64),
Email()])
password = PasswordField('New Password', validators=[
Required(), EqualTo('password2', message='Passwords must match')])
password2 = PasswordField('Confirm password', validators=[Required()])
submit = SubmitField('Reset Password')
def validate_email(self, field):
if User.query.filter_by(email=field.data).first() is None:
raise ValidationError('Unknown email address.')
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
@auth.route('/reset/<token>', methods=['GET', 'POST'])
def reset_password(token):
s = Serializer(current_app.config['SECRET_KEY'])
try:
data = s.loads(token)
except:
raise ValidationError()
user_id = data['reset']
....
class User(UserMixin, db.Model):
__tablename__ = 'users'
...
def reset_password(self, new_password):
self.password = new_password
db.session.add(self)
return True
哦,好吧,既然你提到了,那是真的!我没想到我改变了整个问题,你知道怎么做吗?