此前我們創建了登錄、註冊模塊,那麼自然也需要有身份的轉變,如從遊客→用戶
這裏我們使用Flask-Principal來實現用戶的權限設置
首先,安裝Flask-Principal
那相應地,我們需要一個身份表來表示身份
先添加關聯表(models.py)
roles = Table('role_users', db.Model.metadata,
Column('u_id', Integer(), ForeignKey('user.id')),
Column('r_id', Integer(), ForeignKey('role.id')))
給User表添加關聯(models.py)
class User(db.Model):
...
roles = relationship('Role', secondary=roles, backref=backref('users', lazy='dynamic'))
添加Role表(models.py)
class Role(db.Model):
id = Column(Integer(), primary_key=True)
name = Column(String(80), unique=True)
description = Column(String(255))
def __init__(self, name):
self.name = name
def __repr__(self):
return "<Role '{}'>".format(self.name)
接着,我們在shell中爲role表添加3個角色(管理員,文章作者,默認用戶)
開始對Principal進行初始化:
Flask Principal提供了兩種Need對象:UserNeed和RoleNeed
每種身份會關聯到Need對象(定義了該身份能做什麼事情)
打開extensions.py:
from flask_principal import Principal, Permission, RoleNeed
principals = Principal()
admin_permission = Permission(RoleNeed('admin'))
poster_permission = Permission(RoleNeed('poster'))
default_permission = Permission(RoleNeed('default'))
...
在app中註冊:
from webapp.extensions import bcrypt, login_manager, principals
from flask_principal import identity_loaded, UserNeed, RoleNeed
from flask_login import current_user
def create_app(object_name):
...
principals.init_app(app)
@identity_loaded.connect_via(app)
def on_identity_loaded(sender, identity):
identity.user = current_user
if hasattr(current_user, 'id'):
identity.provides.add(UserNeed(current_user.id))
if hasattr(current_user, 'roles'):
for role in current_user.roles:
identity.provides.add(RoleNeed(role.name))
其中,我們結合了flask_login的current_user來獲取當前用戶狀態(身份)
在create_app()函數中定義了on_identity_loaded()函數:來獲取用戶的權限(角色)
然後我們需要進行身份的轉變,如:遊客→文章作者,遊客→管理員:
我們打開main,py修改視圖函數:
from flask_principal import Identity, AnonymousIdentity, identity_changed
from flask import current_app
...
@main_blueprint.route('/login', methods=['GET', 'POST'])
def login():
if form.validate_on_submit():
...
if form.validate():
login_user(user, remember=form.remember.data)
identity_changed.send(current_app._get_current_object(), identity=Identity(user.id))
return redirect(request.args.get('next') or url_for('main.index'))
@main_blueprint.route('/logout', methods=['GET', 'POST'])
def logout():
from flask_login import logout_user
logout_user()
identity_changed.send(current_app._get_current_object(), identity=AnonymousIdentity())
...
那麼我們現在就可以使用角色權限了,比如只有文章作者纔可以進入文章編輯頁面:
我們打開blog.py:
from flask_login import login_required
from webapp.extensions import poster_permission
@blog_blueprint.route('/edit/<int:id>', methods=['GET', 'POST'])
@login_required
@poster_permission.require(http_exception=403)
def edit_post(id):
...
因爲我們希望管理員也有權限進行修改,所以可以改成
from webapp.extensions import poster_permission, admin_permission
from flask_principal import Permission, UserNeed
from flask import abort
@blog_blueprint.route('/edit/<int:id>', methods=['GET', 'POST'])
@login_required
@poster_permission.require(http_exception=403)
def edit_post(id):
post = Post.query.get_or_404(id)
permission = Permission(UserNeed(post.user.id))
if permission.can() or admin_permission.can():
form = PostForm()
if form.validate_on_submit():
post.title = form.title.data
post.text = form.text.data
post.publish_date = datetime.datetime.now()
db.session.add(post)
db.session.commit()
return redirect(url_for('blog.post', post_id=post.id))
form.text.data = post.text
return render_template('edit.html', form=form, post=post)
abort(403)