《Flask Web開發:基於Python的Web應用開發實戰》學習筆記(二)

轉載於:http://pdf.us/2017/10/05/492.html,感謝這位大神

《Flask Web開發:基於Python的Web應用開發實戰》學習筆記

這裏是第二部分的學習筆記。第二部分:實例:社交博客程序

第八章 用戶認證

用到的擴展

Flask-Login:管理已登錄用戶的用戶會話
Werkzeug:計算密碼散列並覈對
istdangerous:生成並覈對加密安全令牌Flask-Mail:發送與認證相關的密碼
Flask-Bootstrap:HTML模板
Flask-WTF:Web表單
使用Werkzeug實現密碼散列

Werkzeug的security模塊可以實現計算密碼散列。主要用於用戶註冊和驗證用戶。

generate_password_hash(password,method=pbkdf2:sha1,salt_length=8)  以密碼作爲輸入,輸出密碼的散列值

check_password_hash(hash,password)  返回True即表示驗證通過

程序從7a版本開始推進。數據庫改用mysql。先不要建表,db init;db migrate;db upgrade生成當前數據庫。

對app/models.py中User模型做改造:

關於@property@password.setter裝飾器
把一個getter方法變成屬性,只需要加上@property就可以了,此時,@property本身又創建了另一個裝飾器@password.setter,負責把一個setter方法變成屬性賦值
簡單講,@property附加到那個方法上,該方法變爲同名屬性,並只具有讀屬性
而要設置屬性的值,需要使用另外一個方法,並附加@方法名.setter,這樣提供了寫屬性
一句話就是對屬性讀寫分別處理,如果沒有setter,則屬性爲只讀

hash後的加密串,即使相同的密碼加密,hash串也不相同

該功能的單元測試用例:

創建認證藍本

對於不同的程序功能,使用不同的藍本,這樣可以使代碼保持整齊有序。

藍本:auth/__init__.py

auth/views.py

auth/login.html位於app/templates/目錄下。當然,藍本也可以定義自己的模板文件夾,此時,render_template()會先搜索程序文件夾,再搜索藍本配置的模板文件夾。

在create_app函數中附加藍本auth到程序:app/__init__.py

url_prefix是可選參數,使用該參數後,藍本中定義的所有路由都會加上指定前綴,這裏,/login變成了/auth/login。

使用Flask-Login認證用戶

pip install flask-login

使用Flask-Login擴展,User模型需要實現如下幾個方法:

屬性/方法說明
is_authenticated若用戶已登錄,則返回True,否則返回False
is_active若允許用戶登錄,則返回True,否則返回False;禁用用戶,可返回False
is_anonymous對普通用戶返回False
get_id()必須返回用戶唯一標識符,使用Unicode編碼

這四個方法可以直接在User類中實現,更簡單的方法是使用Flask-Login提供的UserMixin類。

app/modles.py

初始化:app/__init__.py

session_protection可設置爲None,'basic','strong',當設置爲‘strong'時,會記錄客戶端IP和瀏覽器用戶代理信息,發現異動就登出用戶。

Flask-Login要求實現一個回調函數,使用指定的標識符加載用戶:app/models.py

回調函數接收以Unicode字符串形式表示的用戶標識符,若存在該用戶,則返回用戶對象,否則返回None

保護路由

讓一個路由僅讓認證的用戶能訪問,未認證用戶訪問,Flask-Login會攔截請求,把用戶發往登錄頁面,示例如下:

添加登錄表單

app/auth/forms.py

app/templates/base.html

<ul class="nav navbar-nav navbar-right">
{% if current_user.is_authenticated %}
<li><a href="{{ url_for('auth.logout') }} ">Sign Out</a></li>
{% else %}
<li><a href="{{ url_for('auth.login') }}">Sign In</a></li>
{% endif %}
</ul>

current_user由Flask-Login定義, 在視圖函數和模板中自動可用,這個變量的值是當前登錄的用戶,若未登錄,則是匿名用戶代理對像。

登入用戶

app/auth/views.py

app/templates/auth/login.html

 

{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title %}Flasky - Login{% endblock %}

{% block page_content %}
<div class="page-header">
<h1>Login</h1>
</div>
<div class="col-md-4">
{{ wtf.quick_form(form) }}
</div>
{% endblock %}

 

登出用戶

app/auth/views.py

測試登錄

shell中註冊新用戶

>>> u=User(email='[email protected]',username='ma',password='admin')
>>> db.session.add(u)
>>> db.session.commit()
{% if current_user.is_authenticated %}
{{ current_user.username }}
{% else %}
Stranger
{% endif %}
註冊新用戶

用戶註冊表單:

注意,validator是複數:validators

其中,驗證函數Regexp是正則表達式驗證,第一個參數是正則表達式(包含字母、數字、下劃線和點),第二個是表達式的旗標(通常爲0),第三個是匹配失敗時的錯誤消息。

密碼的驗證使用EqualTo,放到任意一個就可以,另一個字段做爲參數傳入。

自定義的驗證函數:以validate_開頭,後面跟字段名的方法。該方法會和常規驗證函數一起調用。

註冊表單的渲染:

{% import "bootstrap/wtf.html" as wtf %}
{{ wtf.quick_form(form) }}

註冊新用戶的視圖函數:

確認帳戶

驗證郵箱,通過點擊包含令牌的URL,修改標記狀態。

itsdangerous提供多種生成令牌方法,其中TimedJSONWebSignatureSerializer類生成具有過期時間的JSON Web簽名,該類構造函數接收參數是一個密鑰和過期時間(秒)。dumps方法爲指定數據生成加密的令牌字符串,load方法解碼令牌。

python manage.py shell
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
s=Serializer(app.config['SECRET_KEY'],expires_in=3600)
token=s.dumps({'confirm':23})   #生成token,簽名字符串
data=s.loads(token)                   #data={u'confirm':23}

修改模型:app/models.py

發送確認郵件

app/auth/views.py

因爲只有提交數據庫後才能夠得到新用戶id,而生成token需要用到用戶id,所以需要添加db.session.commit()

模板:{{ url_for('auth.confirm',token=token,_external=True) }}

確認token:

藍本中的程序全局請求鉤子-before_app_request

重新發送確認郵件

管理帳戶

修改密碼

重設密碼

修改電子郵件

先確認郵件進行確認,輸入新郵件地址後,向該郵件地址發送一封包含令牌的郵件。服務器發送令牌前,可先將郵件地址存到臨時表或者是直接存到token中。

第九章 用戶角色

角色在數據庫中的表示

app/models.py,添加兩個屬性

default = db.Column(db.Boolean,default=False,index=True)
permissions = db.Column(db.Integer)

其中permissions字段使用二進制位表示不同的權限。

權限常量:

class Permission:
FOLLOW=0x01                                 #0b00000001關注其它用戶
COMMENT=0x02                             #0b00000010在他人文章後發表評論
WRITE_ARTICLES=0x04                    #0b00000100寫文章
MODERATE_COMMENTS=0x08       #0b00001000管理他人發表的評論
ADMINISTER=0x80                           #0b10000000管理員

用戶角色:

用戶角色權限權限說明
匿名0b000000000x00未登錄用戶,僅閱讀權限
用戶0b000001110x07寫文章,寫評論,關注其他用戶
協管員0b000011110x0f增加管理他人評論功能
管理員0b111111110xff所有權限,包括修改其它用戶權限

通過insert_roles方法添加角色,使用shell操作,Role.insert_roles()

賦予角色

app/models.py

角色驗證

添加輔助方法:app/models.py

can方法使用位與操作,檢查用戶權限。Anonymous類出於一致性考慮,無論用戶是否登錄,均可使用current_user.can()和current_user.is_administrator()方法來驗證用戶權限。

檢查用戶權限的自定義修飾器

app/decorators.py

自定義修飾器的使用方法

模板中也需要檢查權限,爲避免每次調用render_template()時都多添加一個模板參數,可以使用上下文處理器,上下文處理器能讓變量在所有模板中全局可訪問

app/main/__init__.py

@main.app_context_processor
def inject_permissions():
return dict(Permission=Permission)

第十章 用戶資料

資料信息

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章