摘要:認(rèn)證管理新建數(shù)據(jù)庫需要的插件用來發(fā)送認(rèn)證信息用于管理用于密碼加鹽表單對象創(chuàng)建渲染建立認(rèn)證藍(lán)圖建立用戶模型權(quán)限分配權(quán)限等級設(shè)置直接新建一個對象來表示權(quán)限設(shè)置三種用戶角色角色權(quán)限描述只讀基礎(chǔ)權(quán)限只有一個修改評論權(quán)限多一個管理員權(quán)限建
認(rèn)證管理 新建數(shù)據(jù)庫
create database `flasky` default character set utf8 collate utf8_general_ci;需要的插件
flask-mail: 用來發(fā)送認(rèn)證信息 flask-login: 用于管理session werzeug+itsdangerous:用于密碼hash加鹽 flask-wtf:表單對象創(chuàng)建 flask-bootstrap: bootstrap 渲染建立認(rèn)證藍(lán)圖
# auth/__init__.py # coding: utf-8 from flask import Blueprint auth_bp = Blueprint("/",__name__) from . import views,routes,models # app/__init__.py def create_app(config_name): ... from app.auth import auth_bp app.register_blueprint(auth_bp)建立用戶ORM模型
# auth/models.py # coding: utf-8 from werkzeug.security import generate_password_hash,check_password_hash from app import db class User(db.Model): __tablename__ = "users" id = db.Column(db.Integer,primary_key=True) username = db.Column(db.String(12)) email = db.Column(db.String(50)) password_hash = db.Column(db.String(128)) role_id = db.Column(db.Integer,db.ForeignKey("roles.id")) @property def password(self): raise AttributeError("password is not readable attribute") @password.setter def password(self,password): self.password_hash = generate_password_hash(password) def verify_password(self,password): return check_password_hash(self.password_hash,password)權(quán)限分配 權(quán)限等級設(shè)置
name | permission name | permission value |
---|---|---|
Follow users | FOLLOW | 1 |
Comment on posts made by others | COMMENT | 2 |
Write articles | WRITE | 4 |
Moderate comments | MODERATE | 8 |
Admin | ADMIN | 16 |
直接新建一個 Permission 對象來表示權(quán)限
# auth/models.py class Permission: FOLLOW = 1 COMMENT = 2 WRITE = 4 MODERATE = 8 ADMIN = 16
設(shè)置三種用戶角色
角色 | 權(quán)限 | 描述 |
---|---|---|
None | None | 只讀 |
User | FOLLOW/COMMENT/WRITE | 基礎(chǔ)權(quán)限 |
Moderator | MODERATOR | 只有一個修改評論權(quán)限 |
ADMIN | FOLLOW/COMMENT/WRITE/MODERATOR/ADMIN | 多一個管理員權(quán)限 |
# auth/models.py # coding: utf-8 from werkzeug.security import generate_password_hash,check_password_hash from app import db class Role(db.Model): __tablename__ == "roles" id = db.Column(db.Integer,primary_key=True) name = db.Column(db.String(10)) default = db.Column(db.Boolean,default=False,index=True) # 只設(shè)置給一個用戶,其他用戶都是False,因為app 會去搜索這個值,因此設(shè)置為 index 方便查找 permissions = db.Column(db.Integer) users = db.relationship("User",backref="role",lazy="dynamic") def __init__(self,**kw): super(Role,self).__init__(**kw) if self.permissions is None: self.permissions = 0 # 判斷是否含有權(quán)限 def has_permission(self,perm): return self.permissions & perm == perm # 添加權(quán)限 def add_permission(self,perm): if not self.has_permission(perm): self.permissions += perm # 移除權(quán)限 def remove_permission(self,perm): if self.has_permission(perm): self.permissions -= perm # 重置權(quán)限 def reset_permission(self): self.permissions = 0 # 插入角色 @staticmethod def insert_roles(): roles = { "User":[ Permission.FOLLOW, Permission.COMMENT, Permission.WRITE, ], "Moderator":[ Permission.MODERATE ], "ADMIN":[ Permission.FOLLOW, Permission.COMMENT, Permission.WRITE, Permission.MODERATE, Permission.ADMIN, ] } # 默認(rèn)角色是用戶 default_role = "User" for r in roles: # 搜索三種角色,在數(shù)據(jù)庫表的存在 role = Role.query.filter_by(name=r).first() # 如果不存在這種角色,馬上添加進去,方便以后拓展 if role is None: role = Role(name=r) # 重置權(quán)限 role.reset_permission() for perm in roles[r]: # 權(quán)限重新一個個加進去 role.add_permission(perm) # 將默認(rèn)用戶寫進數(shù)據(jù)庫 role.default = (role.name == default_role) db.session.add(role) db.session.commit()
然后是分配角色給用戶
# app/auth/models.py class User(db.Model): def __init__(self,**kw): super(User,self).__init__(**kw) # 分配管理員角色 if self.role is None and self.email == current_app.config["FLASKY_ADMIN"]: self.role = Role.query.filter_by(name="ADMIN").first() # 如果一個用戶的角色不存在 if self.role is None: # 分配一個默認(rèn)角色 self.role = Role.query.filter_by(default=True).first() # 判斷用戶角色 def can(self,perm): return self.role is not None and self.role.has_permission(perm) def is_administrator(self): return self.can(Permission.ADMIN)
接著要將這個插入角色的操作寫進deploy命令,后面使用 flask deploy 即可部署
# run.py @app.cli.command() def deploy(): Role.insert_roles()flask-migrate
pipenv install flask-migrate
運行創(chuàng)建數(shù)據(jù)庫表
flask db init flask db migrate -m "add users and roles table" flask db upgrade單元測試
先配置flask 命令
# run.py @app.cli.command() def test(): import unittest tests = unittest.TestLoader().discover("tests") unittest.TextTestRunner(verbosity=2).run(tests)
新建 tests 文件夾 在根文件夾下
mkdir tests
新建單元測試文件
# tests/test_user_models.py # 用戶模型測試腳本 import unittest from app.auth.models import User class UserModelTestCase(unittest.TestCase): def test_password_enter(self): u = User(password="cat") self.assertTrue(u.password_hash is not None) def test_no_password_getter(self): u = User(password="cat") with self.assertRaises(AttributeError): u.password def test_password_verification(self): u = User(password="cat") self.assertTrue(u.verify_password("cat")) def test_password_salts_are_random(self): u = User(password="cat") u1 = User(password = "cat") self.assertFalse(u1.password_hash == u.password_hash) # 角色模型測試腳本 # tests/test_user_role.py import unittest from app.auth.models import Role,Permission,User class TestUserRole(unittest.TestCase): def test_default_user(self): u = User(username="john",password="cat") self.assertTrue(u.can(Permission.COMMENT)) self.assertTrue(u.can(Permission.WRITE)) self.assertTrue(u.can(Permission.FOLLOW)) def test_moderator_user(self): u = User(username="john_moder",password="123") u.role = Role.query.filter_by(name="Moderator").first() self.assertTrue(u.can(Permission.MODERATE)) self.assertFalse(u.can(Permission.FOLLOW)) self.assertFalse(u.can(Permission.COMMENT)) self.assertFalse(u.can(Permission.WRITE)) def test_admin_user(self): u = User(username="john_admin",password="123") u.role = Role.query.filter_by(name="ADMIN").first() self.assertTrue(u.can(Permission.MODERATE)) self.assertTrue(u.can(Permission.FOLLOW)) self.assertTrue(u.can(Permission.COMMENT)) self.assertTrue(u.can(Permission.WRITE)) self.assertTrue(u.can(Permission.ADMIN))運行部署初始化和單元測試
flask deploy flask test
代碼:https://github.com/TheFifthMa...
參考推薦閱讀: 《OReilly.Flask.Web.Development.2nd.Edition》
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/45042.html
摘要:寫在前面在一款應(yīng)用的整個生命周期,我們都會談及該應(yīng)用的數(shù)據(jù)安全問題。用戶的合法性與數(shù)據(jù)的可見性是數(shù)據(jù)安全中非常重要的一部分。 寫在前面 在一款應(yīng)用的整個生命周期,我們都會談及該應(yīng)用的數(shù)據(jù)安全問題。用戶的合法性與數(shù)據(jù)的可見性是數(shù)據(jù)安全中非常重要的一部分。但是,一方面,不同的應(yīng)用對于數(shù)據(jù)的合法性和可見性要求的維度與粒度都有所區(qū)別;另一方面,以當(dāng)前微服務(wù)、多服務(wù)的架構(gòu)方式,如何共享Sessi...
摘要:自己在前后端分離上的實踐要想實現(xiàn)完整的前后端分離,安全這塊是繞不開的,這個系統(tǒng)主要功能就是動態(tài)管理,這次實踐包含兩個模塊基于搭建的權(quán)限管理系統(tǒng)后臺編寫的前端管理。 自己在前后端分離上的實踐 要想實現(xiàn)完整的前后端分離,安全這塊是繞不開的,這個系統(tǒng)主要功能就是動態(tài)restful api管理,這次實踐包含兩個模塊,基于springBoot + shiro搭建的權(quán)限管理系統(tǒng)后臺bootshir...
摘要:自己在前后端分離上的實踐要想實現(xiàn)完整的前后端分離,安全這塊是繞不開的,這個系統(tǒng)主要功能就是動態(tài)管理,這次實踐包含兩個模塊基于搭建的權(quán)限管理系統(tǒng)后臺編寫的前端管理。 自己在前后端分離上的實踐 要想實現(xiàn)完整的前后端分離,安全這塊是繞不開的,這個系統(tǒng)主要功能就是動態(tài)restful api管理,這次實踐包含兩個模塊,基于springBoot + shiro搭建的權(quán)限管理系統(tǒng)后臺bootshir...
閱讀 3588·2019-08-30 15:55
閱讀 1383·2019-08-29 16:20
閱讀 3668·2019-08-29 12:42
閱讀 2671·2019-08-26 10:35
閱讀 1022·2019-08-26 10:23
閱讀 3420·2019-08-23 18:32
閱讀 907·2019-08-23 18:32
閱讀 2902·2019-08-23 14:55