Я новичок в Python и Flask (и даже SO), поэтому прошу прощения за мой ниже стандартный код, и если в моем вопросе отсутствуют какие-либо необходимые детали, пожалуйста, держите меня в курсе.Попытка поиска ответа (прочитайте множество учебных пособий, подобных этим ), но безуспешно. Это было самое близкое совпадение на SO, насколько я понимаю, но у меня не сработало.
В моем приложении SQLite БД и Flask-Login для аутентификации.Я пытаюсь сбросить пароль для зарегистрированного пользователя.Таким образом, пользователь нажимает кнопку «Забыли пароль» на странице входа (если пользователь не был зарегистрирован, он перенаправляется на страницу регистрации), и это приводит к другой странице, где я запрашиваю зарегистрированный идентификатор электронной почты.Отправьте электронное письмо пользователю со ссылкой для подтверждения, и после того, как он щелкнет по нему, перейдите на страницу сброса пароля.
Эта страница сброса пароля (связанный вид) создает проблему, насколько я понимаю.Здесь пользователь вводит новый пароль, но он не обновляется в моей базе данных.После сброса предполагаемая маршрутизация на страницу входа в систему происходит с сообщением об успешном завершении, но на самом деле, когда я пытаюсь войти с новым паролем, происходит сбой, потому что он все еще аутентифицируется со старым паролем.Хотя есть и значение DateTime, которое я одновременно пытался ввести во время сброса пароля, и эта запись прошла успешно.
Надеюсь, я достаточно хорошо передал свой запрос.Вот 3 просмотров , которые я создал для этого процесса сброса пароля:
# View for Password Reset form:
@app.route("/password_reset", methods=["GET","POST"])
def password_reset():
form = PasswordResetForm()
if form.validate_on_submit():
user = User.query.filter_by(email=form.email.data).first()
if user is None:
flash(u"Invalid/Unknown email address.")
return render_template("password_reset.html", form=form)
elif user is not None and form.new_password.data != form.new_pass_confirm.data:
flash(u"Password mismatch!")
return render_template("password_reset.html", form=form)
else:
user.passwordUpdated_on = datetime.now()
user.password = form.new_password.data #This is my problem line, I guess.
db.session.add(user)
db.session.commit()
flash("Password has been successfully updated!")
return redirect(url_for("login"))
return render_template("password_reset.html", form=form)
# Helper function to redirect User after clicking on password reset link:
@app.route("/reset/<token>")
def pwdreset_email(token):
try:
email = pwdreset_token(token)
except:
flash("Your password reset link is invalid or has expired.")
return redirect(url_for("support"))
return redirect(url_for("password_reset"))
# User Registration/Signup View:
@app.route("/forgot_password", methods=["GET","POST"])
def forgot_password():
form = ForgotPasswordForm()
if form.validate_on_submit():
# If User is registered with us:
user = User.query.filter_by(email=form.email.data).first()
if user is None:
flash(u"Unknown email address!")
return render_template("forgot_password.html", form=form)
# If User is registered and confirmed, sending Password Reset email:
if user.confirmed:
token = generate_pwdreset_token(user.email)
reset_url = url_for("pwdreset_email", token=token, _external=True)
html = render_template("password_email.html", confirm_url=reset_url)
subject = "Password Reset!"
send_email(user.email, subject, html)
db.session.add(user)
db.session.commit()
flash(u"Kindly check registered email for a password reset link!")
# Routing User to Login page:
return redirect(url_for("login"))
elif user.confirmed is False:
flash(u"Your email address must be confirmed before attempting a password reset.")
return redirect(url_for("unconfirmed"))
# Rendering a template for User to initiate Password Reset:
return render_template("forgot_password.html", form=form)
Вот моя Модель :
class User(db.Model, UserMixin):
__tablename__ = "users"
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(64), unique=True, index=True, nullable=False)
username = db.Column(db.String(64), unique=True, nullable=False)
password_hash = db.Column(db.String(256), nullable=False)
passwordUpdated_on = db.Column(db.DateTime, nullable=True)
confirmed = db.Column(db.Boolean, nullable=False, default=False)
def __init__(self, email, username, password, passwordUpdated_on=None, confirmed=False):
self.email = email
self.username = username
self.password_hash = generate_password_hash(password) #Werkzeug
self.passwordUpdated_on = passwordUpdated_on
self.confirmed = confirmed
def check_password(self, password):
return check_password_hash(self.password_hash, password)
Вотмоя конфигурация скрипт:
class BaseConfig(object):
"""
Base configuration for Database and Mail settings.
"""
# Creating Database with preferred settings:
basedir = abspath(dirname(__file__))
SQLALCHEMY_DATABASE_URI = "sqlite:///" + join(basedir, "my_data.sqlite")
SQLALCHEMY_TRACK_MODIFICATIONS = False
SECURITY_RECOVERABLE = True # Added this looking at other SO answer. Haven't yet read about it.
# Main Application configuration:
SECRET_KEY = "random_key"
SECURITY_PASSWORD_SALT = "random_password"
WTF_CSRF_ENABLED = True
DEBUG_TB_ENABLED = False
DEBUG_TB_INTERCEPT_REDIRECTS = False
Наконец мои формы :
class ForgotPasswordForm(FlaskForm):
email = StringField("Email Address: ", validators=[DataRequired()])
submit = SubmitField("Reset Password")
class PasswordResetForm(FlaskForm):
email = StringField("Email Address: ", validators=[DataRequired()])
new_password = PasswordField("New Password: ", validators=[DataRequired(), EqualTo("new_pass_confirm")])
new_pass_confirm = PasswordField("Confirm New Password: ", validators=[DataRequired()])
submit = SubmitField("Update Password")
А также мой пароль_установка шаблон ниже:
<form action="" method="POST">
{{ form.hidden_tag() }}
<div class="form-group">
<label for="email">Email Address: </label>
<input type="email" class="form-control form-control-sm" name="email" id="email" aria-describedby="emailHelp" value="">
</div>
<div class="form-group">
<label for="new_password"><h5 style="font-family:verdana; color: #514e0d"><b>New Password: </b></h5></label>
<input type="password" class="form-control form-control-sm" name="new_password" id="new_password" value="">
</div>
<div class="form-group">
<label for="new_pass_confirm">Confirm New Password: </label>
<input type="password" class="form-control form-control-sm" name="new_pass_confirm" id="new_pass_confirm" value="">
</div>
<div class="row">
<div class="col">
<a class="btn btn-warning btn-lg" href="{{ url_for("support") }}" role="button">Support </a>
</div>
<div class="col">
<button type="submit" class="btn btn-success btn-lg float-right">Update Password</button>
</div>
</div>
<br>
</form>
Любая подсказка будет высоко оценена.Спасибо за ваше время и еще раз, если я пропустил предоставление какой-либо необходимой информации, пожалуйста, дайте мне знать.
Решение: В моих models.py ,Я добавил:
@property
def password(self):
"""
The password property will call werkzeug.security and
write the result to the 'password_hash' field.
Reading this property will return an error.
"""
raise AttributeError("password is not a readable attribute")
@password.setter
def password(self, password):
self.password_hash = generate_password_hash(password)