проблема с получением токена из моей ссылки на функцию аутентификации токена, чего мне не хватает? - PullRequest
0 голосов
/ 17 апреля 2020

Я пытаюсь использовать на своем веб-сайте функциональность ЗАБЫЛИ ПАРОЛЬ? , я просто генерирую токен с идентификатором пользователя, а затем отправляю форму, где они могут обновить свой пароль вместе с этим токен, но проблема в том, что я не могу получить этот токен после того, как нажму на ссылку, я ничего не получу, может кто-нибудь сказать мне, что именно мне не хватает? вот что я сделал до сих пор:

# generates the token with the user id
def get_reset_password_token(user_id, expires_in=1800):
    return jwt.encode({'reset_password': user_id, 'exp': time() + expires_in},
    app.config['SECRET_KEY'], algorithm='HS256').decode('utf-8')

# verfies the token recovered from the link
def verify_reset_password_token(token):
    try:
        id = jwt.decode(token, app.config['SECRET_KEY'],algorithms=['HS256'])['reset_password']
    except:
        print("token was invalid.")
        return None
    return print("all good")

# sends email to the user containing reset password link
def send_password_reset_email(user_id, user_mail):
    token = get_reset_password_token(user_id)
    msg = Message('[El-menu] Password Reset Request', sender ='noreply@demo.com', recipients =[user_mail])
    msg.body = f'''To reset your password, visit the following link:

{url_for('reset_password', token=token , _external=True)}

If you didn't make this request, ignore this email and no changes will be madeSincerely,

Sincerely,

El-menu Team
'''
    mail.send(msg)

    return  print("email sent with token " + token +" to email " + user_mail, file=sys.stderr)


@app.route("/reset_password_request", methods = ["GET", "POST"])
def reset_password_request():
    if request.method == "POST":
        email = request.form.get("email")

        # checks for valid mail
        if not email:
            error = "you must submit a valid email"
            return render_template("reset_password_request.html", error = error)
        # performs a query to find information about given email, whether it's in the system or not?
        user = db.execute("SELECT * FROM users WHERE email= :email", email = email)


        if user:
            user_mail = user[0]['email']
            user_id = user[0]['id']
            send_password_reset_email(user_id, user_mail)
        password_reset = "Password reset link has been sent to your email!"
        return render_template("login.html", password_reset = password_reset)

    else:
        return render_template("reset_password_request.html")

@app.route('/reset_password/<token>', methods = ["GET", "POST"])
def reset_password(token):
    if request.method == "POST":
        print("trying to reset password now..", file=sys.stderr)
        print(token, file=sys.stderr)
        user_id = verify_reset_password_token(token)
        print(user_id, file=sys.stderr)
        if not user_id:
            print("token is none", file=sys.stderr)
            return redirect(url_for('index'))
        print(user_id, file=sys.stderr)
        password = request.form.get("password")
        confirmation = request.form.get("confirmation")
        # Ensure password was submitted
        if not password:
            error = "You must provide a password"
            return render_template("reset_password.html", error = error)

        # Ensure confirmation was submitted
        elif not confirmation:
            error = "You must provide a password confirmation"
            return render_template("reset_password.html", error = error)

        reg = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[A-Za-z\d@$!#%*?&]{8,}$"

        # compiling regex
        pat = re.compile(reg)

        # searching regex
        mat = re.search(pat, password)

        # validating conditions
        if not mat:
            error = "Password is weak"
            return render_template("reset_password.html", error = error)

        # Ensure Passwords match
        if password != confirmation:
            error = "Password and confirmation must match!"
            return render_template("reset_password.html", error = error)

        # Hash password
        hashed_password = generate_password_hash(password)

        db.execute("UPDATE users SET hash = :hash WHERE id = :id", hash = hashed_password, id = user_id)

        return redirect("/")

    else:
        return render_template("reset_password.html")

Ответы [ 2 ]

0 голосов
/ 17 апреля 2020

Вам необходимо использовать render_template, чтобы создать тело письма, которое понимает, что такое token.

Таким образом, первым шагом будет создание шаблона электронной почты для тела письма. Следующим шагом будет использование render_template и передача токена.

Пример из одного из моих Flask приложений:

message = Message(
    subject=render_template("email/reset_subject.txt"),
    recipients=[user.email]
)

salt = current_app.config.get("SECURITY_PASSWORD_SALT", b"")

message.html = render_template(
    "email/reset.html",
    token=generate_code(user.email, salt=salt)
)
mail.send(message)
0 голосов
/ 17 апреля 2020

Полагаю, это потому, что ссылка, которую вы даете {url_for('reset_password', token=token , _external=True)} в send_password_request_email, делает запрос GET, поэтому пользователь получает reset_password и получает прямое возвращение return render_template("reset_password.html")

...