成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

02-Flask-用戶認(rèn)證和角色管理-數(shù)據(jù)庫設(shè)計

noONE / 1716人閱讀

摘要:認(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

相關(guān)文章

  • 不用 Spring Security 可否?試試這個小而美的安全框架

    摘要:寫在前面在一款應(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...

    toddmark 評論0 收藏0
  • api權(quán)限管理系統(tǒng)與前后端分離實踐

    摘要:自己在前后端分離上的實踐要想實現(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...

    bawn 評論0 收藏0
  • api權(quán)限管理系統(tǒng)與前后端分離實踐

    摘要:自己在前后端分離上的實踐要想實現(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...

    tianlai 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<