flask網頁建設主題五
By: Steven Wang
Tags: Flask

密碼重置功能

發一封郵件 內有一個連結

用戶點擊連結就可以重置密碼

功能牽涉兩個部分

(1)發送郵件

(2)收到郵件可以通過web token技術，驗證是這個郵件是這個用戶伺服器發出的，是用戶的郵箱

安裝pip

Flask-Mail / 發郵件用

pip install flask_mail

PyJWT / 是一種JSON web token(JWT)用來驗證用戶有效合法性

pip install pyjwt

密碼重置請求頁面的實現步驟

(1)製作重置密碼請求的頁面password_reset_request.html

(2–0)flash

(2)form.py / class PasswdResetRequestForm / 接受用戶輸入的請求

(3)login.html / 新增連結 Forgot Password? url_for(‘reset_password_request’)

(4)__init__.py /增加路由app.add_url_rule(‘/reset_password_request’,’reset_password_request’,reset_password_request,methods=[‘GET’,’POST’])

(5)route.py / def reset_password_request()處理用戶GET/POST的請求

reset_password_request.html 有form 需要一個form物件 (form.py / class PasswdResetRequestForm(FlaskForm))

login.html / <a href=”{{ url_for(‘reset_password_request’) }}”>Forgot Password?</a>需要一個url函數reset_password_request

因此在route.py定義一個def reset_password_request() 處理用戶GET/POST的請求

並且在__init__.py去註冊url_rule

步驟說明

(1)一個頁面表格password_reset_request.html，需要一個form

(2–0)flash功能在base.html設定，可以顯示flash功能

flash在頁面上顯示一條消息

在templates/base.html增加一個方法 get_flashed_message()

{% with message = get_flash_message() %}

{% if message %}

<ul>

{% for message in messages %}

<li>{{ message }}</li>

{% endfor %}

</ul>

{% endif %}

{% endwith %}

(2)form.py

class PasswdResetRequestForm(FlaskForm): / 接受用戶輸入的請求

def validate_email(self, email) / 驗證email有沒有在資料庫，確保有註冊帳號在資料庫中

(3)login.html / 新增連結

(4)__init__.py路由註冊reset_password_request，支持GET/POST method

(5)route.py / def reset_password_request() 處理用戶GET/POST的請求

from Flask import flash

flash 應用 / route.py / def reset_password_request()

if current_user.is_authenticated:/如果當前用戶已經登入

return redirect(url_for('index')) / 已登入不需要重設密碼 回到index

form = PasswdResetRequestForm() 初始化一個form

if form.validate_on_submit() / 假如是post

user = User.query.filter_by(email=form.email.data).first() 找到用戶

if user:flash 有的話flash 回到login

假如是get / return render_template(‘password_reset_request.html’, form=form)

如何給發郵件flask_mail

首先做基本的配置config.py

初始化一個mail的對象

使用message的方法創建一個message

用send的方法去發送信件

Google信箱需設定低安全才能發信

JWT (Jason Web Token)的使用

>>> import jwt 加密

>>> encoded_jwt = jwt.encode({'some': 'payload'}, 'secret', algorithm='HS256')

>>> encoded_jwt

'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb21lIjoicGF5bG9hZCJ9.4twFt5NiznN84AWoo1d7KO1T_yoc0Z6XOpOVswacPZg' 解密

>>> jwt.decode(encoded_jwt, 'secret', algorithms=['HS256'])

{'some': 'payload'}

import

class User 新增方法

加密/解密

email = email['email'] 解密之後是一個email字典,用email['email]取出email key的value

並用這個email查詢出該email的User物件

信件傳送加密jwt連結url

route.py / def reset_password_request()

效果

信件會連結到http://127.0.0.1:5000/password_reset/，需製作password_reset相關

(0)models.py / def get_jwt ， def verify_jwt

(1)__init__.py /url註冊password_reset/<token>

(2)route.py / def password_reset(token):

(3)templates / password_reset.html

(4)form.py / password_reset

(0)models.py / def get_jwt ， def verify_jwt

import time

import current_app

impoer jwt

加密

.decode(‘utf-8’)

解密

@staticmethod

因為不知道是哪個User

不能實例instance

因此用靜態方法@staticmethod

返還一個User物件

(1)__init__.py /url註冊password_reset/<token>

(2)route.py / def password_reset(token):

import PasswdResetForm

if current_user.is_authenticated:

return redirect(url_for('index')) / 有登入 直接轉到index.html user = User.verify_jwt(token)

if not user:

return redirect(url_for('login')) / 有問題 過時 轉回到login.html form = PasswdResetForm()

return render_template('password_reset.html', title='Password Reset', form=form) /Get Method 轉到password_reset.html if form.validate_on_submit():

user.set_password(form.password.data)

db.session.commit()

return redirect(url_for('login'))

/POST Method password_reset.html寫入

(3)templates / password_reset.html

(4)form.py / password_reset

效果