zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    mac安装go环境
    Ubuntu-Mininet安装
    安装pyenv
    linux下安装weblogic
    C#常用方法
    jenkins部署net core ——2
    jenkins部署net core ——1
    Inno Steup
    安装两个SQL server 实例
    C#线程启动、暂停、恢复、停止怎么实现
  • 原文地址:https://www.cnblogs.com/cx59244405/p/9747896.html
Copyright © 2011-2022 走看看