Web 程序中的用戶并非都具有同樣地位。在大多數(shù)程序中,一小部分可信用戶具有額外權(quán)
成都創(chuàng)新互聯(lián)專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于成都網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計(jì)、永昌網(wǎng)絡(luò)推廣、小程序定制開發(fā)、永昌網(wǎng)絡(luò)營銷、永昌企業(yè)策劃、永昌品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營等,從售前售中售后,我們都將竭誠為您服務(wù),您的肯定,是我們最大的嘉獎(jiǎng);成都創(chuàng)新互聯(lián)為所有大學(xué)生創(chuàng)業(yè)者提供永昌建站搭建服務(wù),24小時(shí)服務(wù)熱線:13518219792,官方網(wǎng)址:muchs.cn
限,用于保證程序平穩(wěn)運(yùn)行。管理員就是最好的例子,但有時(shí)也需要介于管理員和普通用
戶之間的角色,例如內(nèi)容協(xié)管員。
有多種方法可用于在程序中實(shí)現(xiàn)角色。具體采用何種實(shí)現(xiàn)方法取決于所需角色的數(shù)量和細(xì)
分程度。例如:
1)簡單的程序可能只需要兩個(gè)角色,一個(gè)表示普通用戶,一個(gè)表示管理員。
對于這種情況,在 User 模型中添加一個(gè) is_administrator 布爾值字段就足夠了。
2)復(fù)雜的程序可能需要在普通用戶和管理員之間再細(xì)分出多個(gè)不同等級(jí)的角色。
有些程序甚至不能使用分立的角色,這時(shí)賦予用戶某些權(quán)限的組合或許更合適。
本章介紹的用戶角色實(shí)現(xiàn)方式結(jié)合了分立的角色和權(quán)限,賦予用戶分立的角色,但角色使
用權(quán)限定義。
9.1 角色在數(shù)據(jù)庫中的表示
第 5 章創(chuàng)建了一個(gè)簡單的 roles 表,用來演示一對多關(guān)系。示例 9-1 是改進(jìn)后的 Role 模型。
示例 9-1 app/models.py:角色的權(quán)限
class Role(db.Model): __tablename__ = 'roles' id = db.Column(db.Integer, primary_key=True) # 設(shè)置為主鍵 name = db.Column(db.String(64), unique=True) # 設(shè)置unique唯一 default = db.Column(db.Boolean, default=False, index=True) # index為改字段創(chuàng)建索引,default為設(shè)置默認(rèn)值 permissions = db.Column(db.Integer) # 以數(shù)字表示權(quán)限等級(jí) users = db.relationship('User', backref='role', lazy='dynamic') # 動(dòng)態(tài)關(guān)聯(lián)
只有一個(gè)角色的 default 字段要設(shè)為 True,其他都設(shè)為 False。用戶注冊時(shí),其角色會(huì)被
設(shè)為默認(rèn)角色。
這個(gè)模型的第二處改動(dòng)是添加了 permissions 字段,其值是一個(gè)整數(shù),表示位標(biāo)志。各操
作都對應(yīng)一個(gè)位位置,能執(zhí)行某項(xiàng)操作的角色,其位會(huì)被設(shè)為 1。
顯然,各操作所需的程序權(quán)限是不一樣的。對 Flasky 開說,各種操作如表 9-1 所示。
表9-1 程序的權(quán)限
操 作 位 值 說 明
關(guān)注用戶 0b00000001(0x01) 關(guān)注其他用戶
在他人的文章中發(fā)表評論 0b00000010(0x02) 在他人撰寫的文章中發(fā)布評論
寫文章 0b00000100(0x04) 寫原創(chuàng)文章
管理他人發(fā)表的評論 0b00001000(0x08) 查處他人發(fā)表的不當(dāng)評論
管理員權(quán)限 0b10000000(0x80) 管理網(wǎng)站
注意,操作的權(quán)限使用 8 位表示,現(xiàn)在只用了其中 5 位,其他 3 位可用于將來的擴(kuò)充。
9-1 中的權(quán)限可使用示例 9-2 中的代碼表示。
示例 9-2 app/models.py:權(quán)限常量
class Permission: FOLLOW = 0x01 COMMENT = 0x02 WRITE_ARTICLES = 0x04 MODERATE_COMMENTS = 0x08 ADMINISTER = 0x80
表 9-2 列出了要支持的用戶角色以及定義角色使用的權(quán)限位。
表9-2 用戶角色
用戶角色 權(quán) 限 說 明
匿名 0b00000000(0x00)未登錄的用戶。在程序中只有閱讀權(quán)限
用戶 0b00000111(0x07) 具有發(fā)布文章、發(fā)表評論和關(guān)注其他用戶的權(quán)限。這是新用戶的默認(rèn)角色
協(xié)管員 0b00001111(0x0f) 增加審查不當(dāng)評論的權(quán)限
管理員0b11111111(0xff) 具有所有權(quán)限,包括修改其他用戶所屬角色的權(quán)限
(譯注:有點(diǎn)亂,應(yīng)該結(jié)合程序權(quán)限表9-1和9-2理解:二進(jìn)制bit值共八位<0b后面8個(gè)零>默認(rèn)無權(quán)限用戶是8位全部0,操作分別有5種(關(guān)注,評論,撰寫,屏蔽,管理權(quán)) 從右往左,依次設(shè)置為1,管理權(quán)使第八位。表9-2則是合并權(quán)限組合定義了角色,無權(quán)用戶8位全是零,普通用戶擁有撰寫,評論,關(guān)注三項(xiàng)許可權(quán)限(權(quán)限標(biāo)志位分別是1,2,3),所以二進(jìn)制許可代碼組合就是0b00000111,其他同理
)
示例 9-3 app/models.py::在數(shù)據(jù)庫中創(chuàng)建角色
class Role(db.Model): # ... @staticmethod def insert_roles(): roles = { 'User': (Permission.FOLLOW | Permission.COMMENT | Permission.WRITE_ARTICLES, True), 'Moderator': (Permission.FOLLOW | Permission.COMMENT | Permission.WRITE_ARTICLES | Permission.MODERATE_COMMENTS, False), 'Administrator': (0xff, False) } for r in roles: role = Role.query.filter_by(name=r).first() if role is None: role = Role(name=r) role.permissions = roles[r][0] role.default = roles[r][1] db.session.add(role) db.session.commit()
insert_roles() 函數(shù)并不直接創(chuàng)建新角色對象,而是通過角色名查找現(xiàn)有的角色,然后再
進(jìn)行更新。只有當(dāng)數(shù)據(jù)庫中沒有某個(gè)角色名時(shí)才會(huì)創(chuàng)建新角色對象。如此一來,如果以后
更新了角色列表,就可以執(zhí)行更新操作了。要想添加新角色,或者修改角色的權(quán)限,修改
roles 數(shù)組,再運(yùn)行函數(shù)即可。注意,“匿名”角色不需要在數(shù)據(jù)庫中表示出來,這個(gè)角色
的作用就是為了表示不在數(shù)據(jù)庫中的用戶。
若想把角色寫入數(shù)據(jù)庫,可使用 shell 會(huì)話:
(venv) $ python manage.py shell >>> Role.insert_roles() >>> Role.query.all() [<Role u'Administrator'>, <Role u'User'>, <Role u'Moderator'>]
9.2 賦予角色
用戶在程序中注冊賬戶時(shí),會(huì)被賦予適當(dāng)?shù)慕巧?。大多?shù)用戶在注冊時(shí)賦予的角色都是
“用戶”,因?yàn)檫@是默認(rèn)角色。唯一的例外是管理員,管理員在最開始就應(yīng)該賦予“管理
員”角色。管理員由保存在設(shè)置變量 FLASKY_ADMIN中的電子郵件地址識(shí)別,只要這個(gè)電子
郵件地址出現(xiàn)在注冊請求中,就會(huì)被賦予正確的角色。示例 9-4 展示了如何在 User 模型的
構(gòu)造函數(shù)中完成這一操作。
示例 9-4 app/models.py:定義默認(rèn)的用戶角色
class User(UserMixin, db.Model): # ... # 用戶字段 def __init__(self, **kwargs): super(User, self).__init__(**kwargs) if self.role is None: if self.email == current_app.config['FLASKY_ADMIN']: self.role = Role.query.filter_by(permissions=0xff).first() if self.role is None: self.role = Role.query.filter_by(default=True).first() # ... # 用戶的其他方法
User 類的構(gòu)造函數(shù)首先調(diào)用基類的構(gòu)造函數(shù),如果創(chuàng)建基類對象后還沒定義角色,則根據(jù)
電子郵件地址決定將其設(shè)為管理員還是默認(rèn)角色
9.3 角色驗(yàn)證
為了簡化角色和權(quán)限的實(shí)現(xiàn)過程,我們可在 User 模型中添加一個(gè)輔助方法,檢查是否有指
定的權(quán)限,如示例 9-5 所示。
示例 9-5 app/models.py:檢查用戶是否有指定的權(quán)限
from flask.ext.login import UserMixin, AnonymousUserMixin class User(UserMixin, db.Model): # ... def can(self, permissions): return self.role is not None and (self.role.permissions & permissions) == permissions def is_administrator(self): return self.can(Permission.ADMINISTER) # 匿名用戶類 class AnonymousUser(AnonymousUserMixin): def can(self, permissions): return False def is_administrator(self): return False login_manager.anonymous_user = AnonymousUser
User 模型中添加的 can() 方法在請求和賦予角色這兩種權(quán)限之間進(jìn)行位與操作。如果角色
中包含請求的所有權(quán)限位,則返回 True,表示允許用戶執(zhí)行此項(xiàng)操作。檢查管理員權(quán)限的
功能經(jīng)常用到,因此使用單獨(dú)的方法 is_administrator() 實(shí)現(xiàn)。
出于一致性考慮,我們還定義了 AnonymousUser 類,并實(shí)現(xiàn)了 can() 方法和 is_administrator()
方法。這個(gè)對象繼承自 Flask-Login 中的 AnonymousUserMixin 類,并將其設(shè)為用戶未登錄時(shí)
current_user 的值。這樣程序不用先檢查用戶是否登錄,就能自由調(diào)用 current_user.can() 和
current_user.is_administrator()。
如果你想讓視圖函數(shù)只對具有特定權(quán)限的用戶開放,可以使用自定義的修飾器。示例 9-6
實(shí)現(xiàn)了兩個(gè)修飾器,一個(gè)用來檢查常規(guī)權(quán)限,一個(gè)專門用來檢查管理員權(quán)限。
示例 9-6 app/decorators.py:檢查用戶權(quán)限的自定義修飾器
from functools import wraps
from flask import abort
from flask.ext.login import current_user
def permission_required(permission):
def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if not current_user.can(permission):
abort(403)
return f(*args, **kwargs)
return decorated_function
return decorator
def admin_required(f):
return permission_required(Permission.ADMINISTER)(f)
這兩個(gè)修飾器都使用了 Python 標(biāo)準(zhǔn)庫中的 functools 包,如果用戶不具有指定權(quán)限,則返
回 403 錯(cuò)誤碼,即 HTTP“禁止”錯(cuò)誤。我們在第 3 章為 404 和 500 錯(cuò)誤編寫了自定義的
錯(cuò)誤頁面,所以現(xiàn)在也要添加一個(gè) 403 錯(cuò)誤頁面。
下面我們舉兩個(gè)例子演示如何使用這些修飾器。
from decorators import admin_required, permission_required from .models import Permission @main.route('/admin') @login_required @admin_required def for_admins_only(): return "For administrators!" @main.route('/moderator') @login_required @permission_required(Permission.MODERATE_COMMENTS) def for_moderators_only(): return "For comment moderators!"
在模板中可能也需要檢查權(quán)限,所以 Permission 類為所有位定義了常量以便于獲取。為了
避免每次調(diào)用 render_template() 時(shí)都多添加一個(gè)模板參數(shù),可以使用上下文處理器。上
下文處理器能讓變量在所有模板中全局可訪問。修改方法如示例 9-7 所示。
示例 9-7 app/main/__init__.py:把 Permission 類加入模板上下文
@main.app_context_processor def inject_permissions(): return dict(Permission=Permission)
網(wǎng)站題目:Flask中使用用戶角色role擴(kuò)充Flask的用戶子系統(tǒng)(用戶權(quán)限認(rèn)證系統(tǒng))
轉(zhuǎn)載來源:http://muchs.cn/article46/pisgeg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供關(guān)鍵詞優(yōu)化、企業(yè)建站、外貿(mào)網(wǎng)站建設(shè)、虛擬主機(jī)、網(wǎng)站內(nèi)鏈、自適應(yīng)網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)