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.htmluser = User.verify_jwt(token)
if not user:
return redirect(url_for('login')) / 有問題 過時 轉回到login.htmlform = PasswdResetForm()
return render_template('password_reset.html', title='Password Reset', form=form) /Get Method 轉到password_reset.htmlif 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
效果