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
  • 相关阅读:
    SQL Azure (17) SQL Azure V12
    Microsoft Azure News(5) Azure新DV2系列虚拟机上线
    Azure Redis Cache (3) 在Windows 环境下使用Redis Benchmark
    Azure PowerShell (11) 使用自定义虚拟机镜像模板,创建Azure虚拟机并绑定公网IP(VIP)和内网IP(DIP)
    Windows Azure Virtual Machine (31) 迁移Azure虚拟机
    Windows Azure Web Site (16) Azure Web Site HTTPS
    Azure China (12) 域名备案问题
    一分钟快速入门openstack
    管理员必备的Linux系统监控工具
    Keepalived+Nginx实现高可用和双主节点负载均衡
  • 原文地址:https://www.cnblogs.com/cx59244405/p/9747896.html
Copyright © 2011-2022 走看看