Flask学习笔记(登陆和用户权限)

1、用户认证模块 | Flask-Login

1.1 准备用于登陆的用户模型

模型继承UserMixin

 1 from app import db
 2 from werkzeug.security import generate_password_hash,check_password_hash
 3 from flask_login import UserMixin
 4 from . import login_manger
 5 
 6 @login_manger.user_loader
 7 def load_user(user_id):
 8     return User.query.get(int(user_id))
 9 
10 class Role(db.Model):
11     __tablename__ = 'roles'
12     id = db.Column(db.Integer,primary_key=True)
13     name = db.Column(db.String(64),unique=True)
14     users = db.relationship('User',backref='role')
15     def __repr__(self):
16         return '<Role %r>'%self.name
17 
18 class User(UserMixin,db.Model):
19     __tablename__ = 'users'
20     id = db.Column(db.Integer,primary_key=True)
21     username = db.Column(db.String(64),unique=True,index=True)
22     password_hash = db.Column(db.String(128))
23     role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
24     email = db.Column(db.String(128))
25 
26     @property
27     def password(self):
28         raise AttributeError('密码不可读')
29 
30     @password.setter
31     def password(self,password):
32         self.password_hash = generate_password_hash(password)
33 
34     def verify_password(self,password):
35         return check_password_hash(self.password_hash,password)
36 
37     def __repr__(self):
38         return '<Role %r>'%self.username
app/models.py

初始化登陆

 1 from flask import Flask,render_template
 2 from flask_sqlalchemy import SQLAlchemy
 3 from config import Config
 4 from flask_login import LoginManager
 5 
 6 db = SQLAlchemy()
 7 login_manger = LoginManager()
 8 login_manger.session_protection = 'strong'
 9 login_manger.login_view = 'auth.login'
10 
11 def create_app():
12     app = Flask(__name__)
13     app.config.from_object(Config)
14     Config.init_app(app)
15     db.init_app(app)
16     login_manger.init_app(app)
17     from .main import main as main_blueprint
18     app.register_blueprint(main_blueprint)
19     from .auth import auth as auth_blueprint
20     app.register_blueprint(auth_blueprint,url_prefix='/auth')
21     return app
app/__init__.py

1.2 保护路由

@login_required

 1 from datetime import datetime
 2 from  flask import render_template,session,redirect,url_for
 3 from . import main
 4 from .forms import NameForm
 5 from .. import db
 6 from .. import models
 7 from flask_login import login_required
 8 
 9 
10 @main.route('/',methods=['GET','POST'])
11 @login_required
12 def index():
13     form = NameForm()
14     if form.validate_on_submit():
15         session['name'] = form.name.data
16         session['ip'] = form.ip.data
17         form.name.data=''
18         form.ip.data=''
19         return redirect(url_for('.index'))
20     return render_template('index.html',form=form,name=session.get('name'),ip=session.get('ip'))
app/main/views.py

1.3 登陆页面

在前端可以使用current_user对象

 1 {% extends 'base.html' %}
 2 {% block head %}{{ super() }}{% endblock %}
 3 {% block title %}登陆{% endblock %}
 4 {% block body %}
 5     <h1>
 6 
 7     </h1>
 8     {% if current_user.is_authenticated %}
 9         <h1>欢迎{{ current_user.username }}</h1>
10         <p><a href="{{ url_for('auth.logout') }}">登出</a></p>
11     {% else %}
12         <h1>登录页面</h1>
13         <form method="post" action="">
14                 {{ form.hidden_tag() }}
15             <p>{{ form.email.label }}{{ form.email }}</p>
16             <p>{{ form.password.label }}{{ form.password }}</p>
17             <p>{{ form.sumbit }}</p>
18             <p>{{ form.remember_me.label }}{{ form.remember_me }}</p>
19         </form>
20         <p><a href="{{ url_for('auth.register') }}">注册</a></p>
21     {% endif %}
22 {% endblock %}
auth/login.html

1.4 登入登出注册用户

login_user('用户模型对象','True/False')

logout_user()

 1 from flask import render_template,redirect,request,url_for,flash
 2 from flask_login import login_user,login_required,logout_user
 3 from . import auth
 4 from ..models import User,db
 5 from .forms import LoginForm,RegistrationForm
 6 
 7 @auth.route('/login',methods=['GET','POST'])
 8 def login():
 9     form = LoginForm()
10     user = User.query.filter_by(email=form.email.data).first()
11     if user is not None and user.verify_password(form.password.data):
12         login_user(user,form.remember_me.data)
13         return redirect(url_for('main.index'))
14     return render_template('auth/login.html',form=form)
15 
16 @auth.route('/logout')
17 @login_required
18 def logout():
19     logout_user()
20     flash('你已经登出了')
21     return redirect(url_for('main.index'))
22 
23 
24 @auth.route('/register',methods=['GET','POST'])
25 def register():
26     form = RegistrationForm()
27     if form.validate_on_submit():
28         user = User(email=form.email.data,username=form.username.data,password=form.password1.data)
29         db.session.add(user)
30         db.session.commit()
31         return redirect(url_for('auth.login'))
32     return render_template('auth/register.html',form=form)
app/auth/views.py

 

2、用户角色权限

还是主要靠程序逻辑来做权限

2.1 在角色模型中添加权限、赋予角色、角色验证

 1 from app import db
 2 from werkzeug.security import generate_password_hash,check_password_hash
 3 from flask_login import UserMixin,AnonymousUserMixin
 4 from . import login_manger
 5 
 6 @login_manger.user_loader
 7 def load_user(user_id):
 8     return User.query.get(int(user_id))
 9 
10 class Permission:
11     FLLOW = 0x01
12     COMMENT = 0x02
13     WRITE_ARTICLES = 0x04
14     MODERATE_COMMENTS = 0x08
15     ADMINISTER = 0x80
16 
17 class Role(db.Model):
18     __tablename__ = 'roles'
19     id = db.Column(db.Integer,primary_key=True)
20     name = db.Column(db.String(64),unique=True)
21     default = db.Column(db.Boolean,default=False,index=True)
22     permissions = db.Column(db.Integer)
23     users = db.relationship('User',backref='role')
24 
25     #创建数据库角色
26     @staticmethod
27     def insert_roles():
28         roles = {
29             'User':(Permission.FLLOW|Permission.COMMENT|Permission.WRITE_ARTICLES,True),
30             'Admin':(0xff,False)
31         }
32         for r in roles:
33             role = Role.query.filter_by(name = r).first()
34             if role is None:
35                 role = Role(name=r)
36             role.permissions = roles[r][0]
37             role.default=roles[r][1]
38             db.session.add(role)
39             db.session.commit()
40 
41     def __repr__(self):
42         return '<Role %r>'%self.name
43 
44 class User(UserMixin,db.Model):
45     __tablename__ = 'users'
46     id = db.Column(db.Integer,primary_key=True)
47     username = db.Column(db.String(64),unique=True,index=True)
48     password_hash = db.Column(db.String(128))
49     role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
50     email = db.Column(db.String(128))
51 
52     #创建的新用户默认是用户权限
53     def __init__(self,**kwargs):
54         super(User,self).__init__(**kwargs)
55         self.role = Role.query.filter_by(default=True).first()
56     
57     @property
58     def password(self):
59         raise AttributeError('密码不可读')
60 
61     @password.setter
62     def password(self,password):
63         self.password_hash = generate_password_hash(password)
64 
65     def verify_password(self,password):
66         return check_password_hash(self.password_hash,password)
67 
68     #角色验证
69     def can(self,permissions):
70         return self.role is not None and (self.role.permissions & permissions) == permissions
71 
72     def is_admin(self):
73         return self.can(Permission.ADMINISTER)
74 
75     def __repr__(self):
76         return '<User %r>'%self.username
77 
78 #匿名角色,主要为了与上面统一
79 class AnonymousUser(AnonymousUserMixin):
80     def can(self,permissions):
81         return False
82 
83     def is_admin(self):
84         return False
85 
86 login_manger.anonymous_user = AnonymousUser
app/models.py

python manage.py shell

Role.insert_roles()

 2.2 定义用户权限验证装饰器

 1 from functools import wraps
 2 from flask import abort
 3 from flask_login import current_user
 4 from .models import Permission
 5 
 6 def permission_required(permission):
 7     def decorator(f):
 8         @wraps(f)
 9         def decorated_function(*args,**kwargs):
10             if not current_user.can(permission):
11                 abort(403)
12             return f(*args,**kwargs)
13         return decorated_function
14     return decorator
15 
16 def admin_required(f):
17     return permission_required(Permission.ADMINISTER)(f)
app/decorators.py

2.3 给需要权限访问的页面加装饰器

 1 from datetime import datetime
 2 from  flask import render_template,session,redirect,url_for
 3 from . import main
 4 from .forms import NameForm
 5 from .. import db
 6 from .. import models
 7 from flask_login import login_required
 8 from ..decorators import admin_required,permission_required
 9 from ..models import Permission
10 
11 @main.route('/',methods=['GET','POST'])
12 @login_required
13 def index():
14     form = NameForm()
15     if form.validate_on_submit():
16         session['name'] = form.name.data
17         session['ip'] = form.ip.data
18         form.name.data=''
19         form.ip.data=''
20         return redirect(url_for('.index'))
21     return render_template('index.html',form=form,name=session.get('name'),ip=session.get('ip'))
22 
23 
24 @main.route('/admin')
25 @login_required
26 @admin_required
27 def admin_only():
28     return render_template('admin.html')
29 
30 
31 @main.route('/user')
32 @login_required
33 @permission_required(Permission.WRITE_ARTICLES)
34 def user_page():
35     return render_template('user.html')
app/main/views.py

 

posted @ 2018-10-06 17:47  隔壁古二蛋  阅读(2827)  评论(0编辑  收藏  举报