Flask-Login Flask-Security 登录与权限控制
2017-11-16 10:17
1676 查看
先看官方例子:
扩展要求数据库必须要有User和Role这两张表以及包含相应的字段,Flask-Security才能够帮助我们生成权限管理的解决方案。举个简单的例子,通过使用Flask-Security, 我们可以用下面的方式创建用户:
更多的API请查看官方文档:https://pythonhosted.org/Flask-Security/api.html使用Flask-Security来做权限控制
当用户没有Admin权限的时候是无法访问这个路由方法的。它会通过flush函数像页面反馈错误信息。如下:
除了roles_required之外,你还可以使用roles_accepted。前者必须严格的拥有所指定的权限,后者是只要拥有其中一个权限就可以。如下:
from flask import Flask, render_template from flask_sqlalchemy import SQLAlchemy from flask_security import Security, SQLAlchemyUserDatastore, \ UserMixin, RoleMixin, login_required # Create app app = Flask(__name__) app.config['DEBUG'] = True app.config['SECRET_KEY'] = 'super-secret' app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://' # Create database connection object db = SQLAlchemy(app) # Define models roles_users = db.Table('roles_users', db.Column('user_id', db.Integer(), db.ForeignKey('user.id')), db.Column('role_id', db.Integer(), db.ForeignKey('role.id'))) class Role(db.Model, RoleMixin): id = db.Column(db.Integer(), primary_key=True) name = db.Column(db.String(80), unique=True) description = db.Column(db.String(255)) class User(db.Model, UserMixin): id = db.Column(db.Integer, primary_key=True) email = db.Column(db.String(255), unique=True) password = db.Column(db.String(255)) active = db.Column(db.Boolean()) confirmed_at = db.Column(db.DateTime()) roles = db.relationship('Role', secondary=roles_users, backref=db.backref('users', lazy='dynamic')) # Setup Flask-Security user_datastore = SQLAlchemyUserDatastore(db, User, Role) security = Security(app, user_datastore) # Create a user to test with @app.before_first_request def create_user(): db.create_all() user_datastore.create_user(email='matt@nobien.net', password='password') db.session.commit() # Views @app.route('/') @login_required def home(): return render_template('index.html') if __name__ == '__main__': app.run()
使用 Flask-Security 创建User和Role
通过Flask-Security我们可以很方便的管理用户权限但是它对我们的model有一定的要求。请看下图:扩展要求数据库必须要有User和Role这两张表以及包含相应的字段,Flask-Security才能够帮助我们生成权限管理的解决方案。举个简单的例子,通过使用Flask-Security, 我们可以用下面的方式创建用户:
from urls import db, User, Role from flask_security import SQLAlchemyUserDatastore, Security # Setup Flask-Security user_datastore = SQLAlchemyUserDatastore(db, User, Role) security = Security(app, user_datastore) db.create_all() # 创建管理员 admin = user_datastore.create_user(email='admin@4paradigm.com', password='admin') # 创建普通用户角色和Admin角色 user_role = user_datastore.create_role(name='User', description='Generic user role') admin_role = user_datastore.create_role(name='Admin', description='Admin user role') # 为admin添加Admin角色(admin_role) user_datastore.add_role_to_user(admin, admin_role)db.session.commit()上面是我初始化数据库的代码。使用SQLAlchemyUserDatastore来封装db, 使用Security封装我们的app。 然后创建用户和角色,并且使用add_role_to_user的方式为用户添加角色。Flask-Security为我们提供了很多有用的方法。请看下面的截图:
更多的API请查看官方文档:https://pythonhosted.org/Flask-Security/api.html
上面说的这些方法都可以很有效的管理我们数据库中User和Role的关系。
使用Flask-Security来做权限控制
角色保护
当我们拥有了用户和角色以后, 就可以很方便的使用Flask-Security的装饰器来保护我们的页面。比如 @roles_required('Admin')可以用来保护一个路由方法。只有当前用户拥有'Admin'的角色的时候才被准许访问。例如下面的使用方法:@app.route('/config/save', methods=['POST']) @roles_required('Admin') def save_config():注:roles_required这个装饰器一定要放在app.route下面。
当用户没有Admin权限的时候是无法访问这个路由方法的。它会通过flush函数像页面反馈错误信息。如下:
除了roles_required之外,你还可以使用roles_accepted。前者必须严格的拥有所指定的权限,后者是只要拥有其中一个权限就可以。如下:
@roles_accepted('editor', 'author')意思是要求用户至少拥有这两种role其中的一种就可以访问。 除了使用装饰器以外,Flask-Security也支持以编码的方式控制权限。例如:
@app.route('/')@app.route('/index', methods=['GET', 'POST'])@login_requireddef index(): if current_user.has_role('Admin'): names = Env.query.all() return render_template('index.html', names=names) else: names = current_user.envs return render_template('index.html', names=names)current_user.has_role方法判断当前用户是属于哪一种角色(current_user是Flask-Security针对Flask-Login做的扩展,作用是在当前session中维护用户的信息)。关于Flask-Security提供的更多方法,请参照文档:https://pythonhosted.org/Flask-Security/api.html
Flask-Login
初始化Flask-Loginfrom flask_login import LoginManager login_manager = LoginManager() login_manager.init_app(app) login_manager.login_view = 'login'使用LoginManager来初始化,并把login_view设置为login方法。 这是为了之后给登录保护使用的。当Flask-Login检测到用户没有登录的时候会把链接重定向到login_view中去。 登录Flask-Security其实就是扩展了其他各种模块。想用它就必须安装其他模块,而且它的封装改变了其他模块的使用方式。 例如Flask-Login有login和logout方法,Flask-Security也有,你需要使用Flask-Security提供的方法进行登录和登出才能做好权限控制,因为原生的Flask-Loing无法保存User和Role相关的信息。你可以这么看待Flask-Security:它的作用就是封装了其他模块,它的底层其实也是调用的其他模块。 举个例子,当你想要做用户登录的时候。我们使用如下的方式:
from flask_security.utils import login_user, logout_user @app.route('/user/register', methods=['GET', 'POST']) def register(): form = forms.RegisterForm() if form.validate_on_submit(): if form.password.data != form.password_again.data: errors = '两次输入的密码不同' return render_template('register.html', form=form, errors=errors) new_user = user_datastore.create_user(email=form.email.data, password=form.password.data) normal_role = user_datastore.find_role('User') db.session.add(new_user) user_datastore.add_role_to_user(new_user, normal_role) login_user(new_user) return redirect(url_for('index')) return render_template('register.html', form=form)这是用户注册的代码。表单验证通过后,使用Flask-Security的方法在数据库中创建用户信息,然后查找User角色,给用户添加为普通用户的权限。然后调用login_user方法进行登录。这里需要注意的是,import的是flask_security.utiles中的login_user方法而不是Flask-Login的。Flask-Security是封装了其他各种模块的存在,所以现在我们是完全使用Flask-Security的方式来进行登录。 登录以后,用户信息(也就是User对象)会自动的保存在session中。 可以通过引入current_user的方式获取当前的用户。如下:
from flask_security import current_user @app.route('/user/login', methods=['POST', 'GET']) def login(): if not current_user.is_anonymous: return redirect(url_for('index')) form = forms.LoginForm() if form.validate_on_submit(): user = User.query.filter_by(email=form.email.data).first() if user is None: form.errors['username_error'] = 'user does not exit' return render_template('login.html', form=form) if not user.password == form.password.data: form.errors['password_error'] = 'password is not right' return render_template('login.html', form=form) login_user(user, remember=True) return redirect(url_for('index')) return render_template('login.html', form=form)上面是登录的代码。import的仍然是Flask-Security的current_user而不是Flask-Login的。 先判断当前的user是不是匿名用户(未登录的就是匿名用户)。如果不是匿名用户,说明已经登录了,就重定向到首页。这里引用了current_user。它其实就是Flask-Security创建的User对象。它包含了所有的User对象的属性和方法。发现用户未登录后,首先判断是不是表单提交以及表单提交是否通过。如果通过了就从数据库中查询出用户的信息。 判断用户是否存在以及填写的密码是否正确。登录后,这个User对象就赋值给current_user了。 可以在模板页面中直接使用current_user。如下:
<div class="col-md-12 column"> <h4> 你好 {{ current_user.email }} </h4> </div>Flask-Login自动会把current_user传递给模板页面,所以直接在页面引用就可以了。 把上面的代码写入到base.html,提取每个用户的邮箱。 并显示登录保护Flask-Security提供了roles_required这种装饰器来进行权限的保护。自然也就提供了login_required的装饰器来进行登录保护。如下:
@app.route('/user/logout') @login_required def logout():当Flask发现用户并没有登录的时候,就会把链接重定向到我们一开始设置的login_view的页面上了。也就是登录页面。
坑
尽量不要把Flask-Login的版本升级到0.4.0, 使用0.3.2就可以了。 因为Flask-Security在封装Flask-Login 0.4.0的时候会报一个找不到token_loader的错误。因为Flask-Login在0.4.0的时候已经不使用这个token了。相关文章推荐
- JAVAWEB开发之Servlet Filter(过滤器)详解包括post和get编码过滤器、URL访问权限控制、自动登录。以及装饰模式的使用
- Struts2拦截器实现登录权限控制(十二)
- 在struts2中使用拦截器(Interceptor)控制登录和权限
- 【Spring实战】----Security4.1.3实现根据请求跳转不同登录页以及登录后根据权限跳转到不同页配置
- (转)Django ====> 实战学习篇十四 处理登录和注销;控制权限
- spring mvc怎么加入权限控制,在未登录前,任何访问url都跳转到login页面;登录成功后跳转至先前的url
- IdentityServer4实现Token认证登录以及权限控制
- Spring Boot+Spring Security+JWT 实现 RESTful Api 权限控制
- 在struts2中使用拦截器(Interceptor)控制登录和权限
- Godtear.Security,基于CAS(Code Access Security)的权限控制(一)
- 学习MVC之租房网站(六)-用户登录和权限控制
- java中使用Filter控制用户登录权限具体实例
- Struts2拦截器 实现未登录拦截和权限控制
- .net core 同时实现网站管理员后台、会员、WebApi登录及权限控制
- shiro权限控制,会话超时跳转登录页面只有iframe跳转,父页面没有跳转
- linux登录权限控制列表
- spring boot 1.5.4 集成shiro+cas,实现单点登录和权限控制
- SpringBoot+shiro整合学习之登录认证和权限控制
- Godtear.Security,基于CAS(Code Access Security)的权限控制(一) (转)
- java权限拦截,控制当前登录用户访问方法,访问路径,并json提示,驳回请求