flask網頁建設主題五

Steven Wang
10 min readDec 3, 2020

--

密碼重置功能

發一封郵件 內有一個連結
用戶點擊連結就可以重置密碼

功能牽涉兩個部分
(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

效果

--

--

Steven Wang
Steven Wang

No responses yet