Flask权限篇flask_principal
来源:互联网 发布:哈工大机械考研知乎 编辑:程序博客网 时间:2024/05/21 18:32
最近写CMDB的时候遇到了一个问题,那就是flask的权限问题,目前我了解到的Flask有3种方案进行权限管理的操作,
- Flask狗书中的十六进制的权限值来实现
- Flask-Security
Flask Principal
先跳过第一种,可能纯属是我技术的原因吧,我觉得有轮子不用反复造的想法,所以就跳过了第一种选择了后面2种框架的,其实Flask也是坑,flask_principal的作者已经不更新了,上次提交代码是5年前。。。。。。。Flask-Security这个也是一个大坑,你的user必须要有email,active 字段,而且你还必须用WTF,局限太大了所以放弃。 如果想要了解这里找到一篇不错的Blog传送门||同上。
我的项目结构树 CMDB/ ├─app/ │ ├─auth/ │ ├─main/ │ ├─static/ │ ├─templates/ │ ├─__init__.py │ ├─config.conf │ ├─models.py ├─manager.py
models.py,必要的模型关系user和role是多对多
from . import db,login_managerfrom flask_sqlalchemy import SQLAlchemyfrom werkzeug.security import generate_password_hash,check_password_hash#转换密码用到的库from flask_login import UserMixin#角色<-->用户,关联表roles_users = db.Table( 'role_user', db.Column('user_id',db.Integer(),db.ForeignKey('user.id')), db.Column('role_id',db.Integer(),db.ForeignKey('role.id')))#角色表class Role(db.Model): __tablename__ = 'role' id = db.Column(db.Integer(),primary_key=True) name = db.Column(db.String(80),unique=True) description = db.Column(db.String(255)) def __repr__(self): return "<Role_id:{0}>".format(self.id)#用户表class User(db.Model,UserMixin): __tablename__ = 'user' id = db.Column(db.Integer(),primary_key=True) username = db.Column(db.String(80),unique=True,nullable=False) password_hash = db.Column(db.String(255)) #多对多关联 roles = db.relationship('Role',secondary='role_user',backref=db.backref('users',lazy='dynamic')) def __repr__(self): return "<User_id:{0}>".format(self.id) # 这个方法是用于用户登录后返回数据库的ID到session中用来登录 @login_manager.user_loader def load_user(id): return User.query.get(int(id)) @property def password(self): raise AttributeError("密码不允许读取,请使用check_password_hash()进行验证密码") #转换密码为hash存入数据库 @password.setter def password(self,password): self.password_hash = generate_password_hash(password) #检查密码 def check_password_hash(self, password): return check_password_hash(self.password_hash,password)
__init__.py,初始化
from flask import Flaskfrom flask_sqlalchemy import SQLAlchemyfrom flask_login import LoginManager,current_user#权限认证需要的包from flask_principal import Principal, Permission, RoleNeed, identity_loaded# 初始化对象db = SQLAlchemy()login_manager = LoginManager()login_manager.session_protection = 'strong' # 让session功能更加强壮login_manager.login_view = 'auth.login' # 制定系统默认的登录页面login_manager.login_message = "请登录后再进行访问该页面!"#初始化Principalprincipals = Principal()#添加admin权限admin_permission = Permission(RoleNeed('admin'))# 工厂化def create_app(): app = Flask(__name__) app.config.from_pyfile('config.conf') db.init_app(app) login_manager.init_app(app) principals.init_app(app) @identity_loaded.connect_via(app) def on_identity_loaded(sender, identity): #设置当前用户身份为login登录对象 identity.user = current_user #添加UserNeed到identity user对象 if hasattr(current_user, 'id'): identity.provides.add(UserNeed(current_user.id)) #每个Role添加到identity user对象,roles是User的多对多关联 if hasattr(current_user, 'roles'): for role in current_user.roles: identity.provides.add(RoleNeed(role.name)) # 注册蓝图 from .main import main as main_blueprint from .auth import auth as auth_blueprint app.register_blueprint(main_blueprint) app.register_blueprint(auth_blueprint) return app
1.identity_loaded :信号实现函数,需要访问 app 对象,所以在 create_app里面构造
2.identity_changed:用户身份变化时发送。
(其实有点复杂我也不是太理解,大家也可以看下其它大神的,我这里就当是一个demo好拉)
auth-views.py,login,logout都需要改变身份。
from . import authfrom .. import db,admin_permissionfrom ..models import Userfrom flask import redirect,render_template,request,url_for,flashfrom flask_login import login_user,logout_user,current_user,login_required# from flask_security import roles_required,current_user,logout_user,login_user,login_requiredfrom flask_principal import Identity, AnonymousIdentity, identity_changed, current_app,IdentityContext#上下文处理,可以在jinja2判断是否有执行权限@auth.app_context_processordef context(): admin= IdentityContext(admin_permission) return dict(admin=admin)#登录@auth.route('/login',methods=['GET','POST'])def login(): if request.method == 'POST': username = request.form['username'] password = request.form['password'] check = request.form.get('check') user = User.query.filter_by(username=username).first() if user and user.check_password_hash(password): if check: login_user(user,remember=True) else: login_user(user) #登录时的身份变化 identity_changed.send( current_app._get_current_object(), identity=Identity(user.id)) return redirect(url_for('main.index')) else: flash("账户或密码错误!") return render_template('login.html')#注销@auth.route('/logout',methods=['GET','POST'])def logout(): logout_user() #注销后身份变成匿名 identity_changed.send( current_app._get_current_object(), identity=AnonymousIdentity()) return redirect(url_for('auth.login'))
需要权限保护的路由
#增加用户@auth.route('/adduser',methods=['GET','POST'])@login_required@admin_permission.require(http_exception=403)def adduser(): if request.method == 'POST': username = request.form['user'] password = request.form['password'] search = User.query.filter_by(username=username).first() if search is None: user = User(username=username,password=password) db.session.add(user) db.session.commit() flash('应该是提交成功了吧。') else: flash('这个用户名应该是有人用了吧。。') return render_template('adduser.html')
前端鉴权,有权限才显示
{% if admin.can() %} <li><a href="{{ url_for('auth.adduser') }}"><i class="fa fa-circle-o"></i>增加用户</a></li> {% endif %}
阅读全文
0 0
- Flask权限篇flask_principal
- 【转】flask权限管理
- flask权限管理功能的实现
- 基于Flask实现后台权限管理系统
- 基于Flask实现后台权限管理系统
- 基于Flask实现后台权限管理系统
- 基于Flask实现后台权限管理系统
- 基于Flask实现后台权限管理系统
- flask源码分析篇
- flask
- flask
- Flask
- Flask
- flask
- flask
- Flask
- Flask
- flask
- 使用XmlDocument创建XML文档及增加删除更新节点
- 解决css边框1px
- C语言的条件编译#if, #elif, #else, #endif、#ifdef, #ifndef
- CodeForces
- 解决AS导入新项目加载时间过长
- Flask权限篇flask_principal
- centos7.3安装php
- Spring中ApplicationContext和beanfactory区别
- c++函数重载详解
- 判断手机版本
- 缓冲区溢出
- linux文件名匹配(通配符使用)
- mybatis动态查询
- 电子书在线阅读网址