【Flask】Flask-Principal介绍译文
来源:互联网 发布:淘宝极有家装修日记 编辑:程序博客网 时间:2024/05/16 18:36
介绍
Flask-Principal提供了非常松散的框架,以绑定两种类型服务机制,它们通常位于一个web应用程序的不同部分。
- 权限认证机制
- 用户信息管理机制
例如,一个权限认证机制采用 OAuth,使用Flask-OAuth,用户信息存储在关系数据库中。框架使用signal消息作为应用接口(松耦合)。
框架主要部分包含身份(Identity),需求(Needs),权限(Permission),和包含身份信息上下文环境(IdentityContext)
- Identity代表用户,并为每个请求(例如会话)保存/加载不同位置。对系统来说,身份是用户的化身。它包含了用户的访问权限。
2.Need是最小原子的访问控制,并代表一个特定参数的情况。例如“管理角色”,“可以编辑博客”。 - Permission是任何时候访问资源,都应该出现的功能。
- IdentityContext是某种身份的背景下针对特定的许可。它可以用于作为一个上下文管理器(context manager)或装饰(decorator)。
保护访问的资源
对用户(不是身份验证机制)进行访问限制很容易使用,可以作为装饰或上下文管理器,下面是示例。
from flask import Flask, Responsefrom flask.ext.principal import Principal, Permission, RoleNeedapp = Flask(__name__)# load the extensionprincipals = Principal(app)# Create a permission with a single Need, in this case a RoleNeed.admin_permission = Permission(RoleNeed('admin'))# protect a view with a principal for that need@app.route('/admin')@admin_permission.require()def do_admin_index(): return Response('Only if you are an admin')# this time protect with a context manager@app.route('/articles')def do_articles(): with admin_permission.require(): return Response('Only if you are admin')
权限认证机制
身份验证机制应该使用identity-changed
信号表明请求已经被验证过。例如,下面的代码是一个例子,如何将流行的Flask-Login与Flask-Principal扩展:
from flask import Flask, current_app, request, sessionfrom flask.ext.login import LoginManager, login_user, logout_user, \ login_required, current_userfrom flask.ext.wtf import Form, TextField, PasswordField, Required, Emailfrom flask.ext.principal import Principal, Identity, AnonymousIdentity, \ identity_changedapp = Flask(__name__)Principal(app)login_manager = LoginManager(app)@login_manager.user_loaderdef load_user(userid): # Return an instance of the User model return datastore.find_user(id=userid)class LoginForm(Form): email = TextField() password = PasswordField()@app.route('/login', methods=['GET', 'POST'])def login(): # A hypothetical login form that uses Flask-WTF form = LoginForm() # Validate form input if form.validate_on_submit(): # Retrieve the user from the hypothetical datastore user = datastore.find_user(email=form.email.data) # Compare passwords (use password hashing production) if form.password.data == user.password: # Keep the user info in the session using Flask-Login login_user(user) # Tell Flask-Principal the identity changed identity_changed.send(current_app._get_current_object(), identity=Identity(user.id)) return redirect(request.args.get('next') or '/') return render_template('login.html', form=form)@app.route('/logout')@login_requireddef logout(): # Remove the user information from the session logout_user() # Remove session keys set by Flask-Principal for key in ('identity.name', 'identity.auth_type'): session.pop(key, None) # Tell Flask-Principal the user is anonymous identity_changed.send(current_app._get_current_object(), identity=AnonymousIdentity()) return redirect(request.args.get('next') or '/')
用户信息管理机制
用户信息管理机制应该接收identity-loaded
信号(signal),对身份实例添加任何信息,比如角色(roles)。下面是另一个使用Flask-Login和连接上面代码的例子。它是一个可使用的基于角色的权限方案。
from flask.ext.login import current_userfrom flask.ext.principal import identity_loaded, RoleNeed, UserNeed@identity_loaded.connect_via(app)def on_identity_loaded(sender, identity): # Set the identity user object identity.user = current_user # Add the UserNeed to the identity if hasattr(current_user, 'id'): identity.provides.add(UserNeed(current_user.id)) # Assuming the User model has a list of roles, update the # identity with the roles that the user provides if hasattr(current_user, 'roles'): for role in current_user.roles: identity.provides.add(RoleNeed(role.name))
你可以把上面代码放在create_app
里。
细粒度的资源保护
现在比如,你仅仅想作者可以发布和编辑文章,这个需要创建Need
和Permission
对象,并对identity_loaded
信号处理程序添加更多的逻辑。例如:
from collections import namedtuplefrom functools import partialfrom flask.ext.login import current_userfrom flask.ext.principal import identity_loaded, Permission, RoleNeed, \ UserNeedBlogPostNeed = namedtuple('blog_post', ['method', 'value'])EditBlogPostNeed = partial(BlogPostNeed, 'edit')class EditBlogPostPermission(Permission): def __init__(self, post_id): need = EditBlogPostNeed(unicode(post_id)) super(EditBlogPostPermission, self).__init__(need)@identity_loaded.connect_via(app)def on_identity_loaded(sender, identity): # Set the identity user object identity.user = current_user # Add the UserNeed to the identity if hasattr(current_user, 'id'): identity.provides.add(UserNeed(current_user.id)) # Assuming the User model has a list of roles, update the # identity with the roles that the user provides if hasattr(current_user, 'roles'): for role in current_user.roles: identity.provides.add(RoleNeed(role.name)) # Assuming the User model has a list of posts the user # has authored, add the needs to the identity if hasattr(current_user, 'posts'): for post in current_user.posts: identity.provides.add(EditBlogPostNeed(unicode(post.id)))
下一步将保护endpoint,允许用户编辑文章。这是通过资源的ID(post_id)创建一个许可对象实例:
@app.route('/posts/<post_id>', methods=['PUT', 'PATCH'])def edit_post(post_id): permission = EditBlogPostPermission(post_id) if permission.can(): # Save the edits ... return render_template('edit_post.html') abort(403) # HTTP Forbidden
来源:http://pythonhosted.org/Flask-Principal/
0 0
- 【Flask】Flask-Principal介绍译文
- Flask-Principal的基本使用
- Flask介绍
- flask
- flask
- Flask
- Flask
- flask
- flask
- Flask
- Flask
- flask
- Flask
- flask
- Flask
- Flask
- flask
- Flask
- 高仿美团客户端 React-Native版,支持iOS、Android
- 查找出数组中符合某一条件的数组索引
- Webx框架:ResourceLoader(转载)
- Android 4.0 Launcher2源码分析——Launcher内容加载详细过程
- Android FragmentTabhost 监听tab点击事件
- 【Flask】Flask-Principal介绍译文
- MLlib数据统计基本概念
- Sudoku Killer
- javascript内置对象(六)
- 用不同的方法实现字符串平移问题
- js调试工具Console命令详解
- window下python软件包安装
- Mysql-MHA高可用实验测试-主从复制搭建
- Easy 14 Plus One(66)