用户认证(二)【使用Flask-Login认证用户】
2016-09-24 17:09
323 查看
Flask-Login扩展,记住认证状态,管理用户认证系统中的认证状态
pip install flask-login
flasky/app/models.py
flasky/app/_init_.py
flasky/app/auth/forms.py登录表单
flasky/app/templates/base.html
判断条件中的变量current_user由Flask-Login定义,且在视图函数和模板中自动调用。
图中代码中Sign Out和Sign in是错的,代码应该是Log Out和Log In才能显示网页中右上角的效果。
flasky/app/auth/views.py
login_user()函数的原型:
flasky/app/templates/auth/login.html
flasky/app/templates/index.html
此外,还有以下改动:
把之前main/views.py的各种复杂的储存用户会话消息name,判断是否是第一次输入,以及发送邮件等等去掉,简化成直接返回index.html模板。
flasky/app/main/views.py
flasky/migrations/versions/456a945560f6_login_support.py
数据库迁移脚本版本
flasky/requirements.txt
所有依赖包的文件
pip install flask-login
准备用于登录的用户模型
flasky/app/models.py
from werkzeug.security import generate_password_hash, check_password_hash from flask_login import UserMixin ###从flask_login导入UserMixin类 ###USerMixin类包含的以上四种方法的默认实现。 from . import db, login_manager ###从程序的工厂函数引入login_manager实例 class Role(db.Model): __tablename__ = 'roles' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(64), unique=True) users = db.relationship('User',backref='role',lazy='dynamic') def __repr__(self): return '<Role %r>' % self.name class User(UserMixin, db.Model): ###User继承UserMixin和db.Model类的功能属性 __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) email = db.Column(db.String(64), unique=True, index=True) ###加入email属性,用来储存用户的email username = db.Column(db.String(64),unique=True, index=True) role_id = db.Column(db.Integer, db.ForeignKey('roles.id')) password_hash = db.Column(db.String(128)) @property def password(self): raise AttributeError('password is not a readable attribute') @password.setter def password(self,password): self.password_hash = generate_password_hash(password) def verify_password(self, password): return check_password_hash(self.password_hash, password) def __repr__(self): return '<User %r>' % self.username @login_manager.user_loader ###加载用户的回调函数接收以Unicode字符串形式表示的用户标示符 ###如果能找到用户,这个函数必须返回用户对象,否则返回None。 def load_user(user_id): return User.query.get(int(user_id))
flasky/app/_init_.py
from flask import Flask from flask_bootstrap import Bootstrap from flask_mail import Mail from flask_moment import Moment from flask_sqlalchemy import SQLAlchemy from flask_login import LoginManager from config import config bootstrap = Bootstrap() mail = Mail() moment = Moment() db = SQLAlchemy() login_manager = LoginManager() login_manager.session_protection = 'strong' login_manager.login_view = 'auth.login' def create_app(config_name): app = Flask(__name__) app.config.from_object(config[config_name]) config[config_name].init_app(app) bootstrap.init_app(app) mail.init_app(app) moment.init_app(app) db.init_app(app) login_manager.init_app(app) from .main import main as main_blueprint app.register_blueprint(main_blueprint) from .auth import auth as auth_blueprint app.register_blueprint(auth_blueprint, url_prefix='/auth') return app
保护路由
添加登录表单
flasky/app/auth/forms.py登录表单
from flask_wtf import Form ###从Flask-WTF扩展导入Form基类 from wtforms import StringField, PasswordField, BooleanField, SubmitField ###从WTForms包中导入字段类 from wtforms.validators import Required, Length, Email ###从WTForms导入验证函数 class LoginForm(Form): email = StringField('Email', validators=[Required(), Length(1, 64), Email()]) ###StringField构造函数中的可选参数validators指定一个有验证函数组成的列表,在接受用户提交的数据之前验证数据。 ###电子邮件字段用到了WTForms提供的Length()和Email()验证函数。 password = PasswordField('Password', validators=[Required()]) ###PasswordField类表示属性为type="password"的<input>元素。 remember_me = BooleanField('Keep me logged in') ###BooleanField类表示复选框。 submit = SubmitField('Log In')
flasky/app/templates/base.html
{% extends "bootstrap/base.html" %} {% block title %}Flasky{% endblock %} {% block head %} {{ super() }} <link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}" type="image/x-icon"> <link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}" type="image/x-icon"> {% endblock %} {% block navbar %} <div class="navbar navbar-inverse" role="navigation"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="{{ url_for('main.index') }}">Flasky</a> </div> <div class="navbar-collapse collapse"> <ul class="nav navbar-nav"> <li><a href="{{ url_for('main.index') }}">Home</a></li> </ul> ######################################## ###判断条件中的变量current_user由Flask-Login定义,且在视图函数和模板中自动调用。 <ul class="nav navbar-nav navbar-right"> {% if current_user.is_authenticated %} <li><a href="{{ url_for('auth.logout') }}">Log Out</a></li> {% else %} <li><a href="{{ url_for('auth.login') }}">Log In</a></li> {% endif %} </ul> ######################################## </div> </div> </div> {% endblock %} {% block content %} <div class="container"> {% for message in get_flashed_messages() %} <div class="alert alert-warning"> <button type="button" class="close" data-dismiss="alert">×</button> {{ message }} </div> {% endfor %} {% block page_content %}{% endblock %} </div> {% endblock %} {% block scripts %} {{ super() }} {{ moment.include_moment() }} {% endblock %}
判断条件中的变量current_user由Flask-Login定义,且在视图函数和模板中自动调用。
图中代码中Sign Out和Sign in是错的,代码应该是Log Out和Log In才能显示网页中右上角的效果。
登入用户
登录路由【视图函数login()】
登出路由【视图函数logout()】
flasky/app/auth/views.py
from flask import render_template, redirect, request, url_for, flash from flask_login import login_user, logout_user, login_required ###从Flask_login导入login_user, logout_user, login_required 函数 from . import auth ###从本级目录中导入auth蓝本 from ..models import User ###从上级目录中的models.py导入User模型 from .forms import LoginForm 从本级目录中的forms.py中导入LoginForm类 @auth.route('/login', methods=['GET', 'POST']) ###当请求为GET时,直接渲染模板,当请求是POST提交时,验证表格数据,然后尝试登入用户。 def login(): form = LoginForm() if form.validate_on_submit():###表格中填入了数据,执行下面操作 user = User.query.filter_by(email=form.email.data).first() ###视图函数使用表单中填写的email加载用户 if user is not None and user.verify_password(form.password.data): ###如果user不是空的,而且验证表格中的密码正确,执行下面的语句,调用Flask_Login中的login_user()函数,在用户会话中把用户标记为登录。 ###否则直接执行flash消息和跳转到新表格中。 login_user(user, form.remember_me.data) ###login_user函数的参数是要登录的用户,以及可选的‘记住我’布尔值。 return redirect(request.args.get('next') or url_for('main.index')) ###用户访问未授权的URL时会显示登录表单,Flask-Login会把原地址保存在查询字符串的next参数中,这个参数可从request.args字典中读取。如果查询字符串中没有next参数,则重定向到首页。 flash('Invalid username or password.') return render_template('auth/login.html', form=form) @auth.route('/logout') ###退出路由 @login_required ###用户要求已经登录 def logout(): logout_user() ###登出用户,这个视图函数调用logout_user()函数,删除并重设用户会话。 flash('You have been logged out.') ###显示flash消息 return redirect(url_for('main.index')) ###重定向到首页
login_user()函数的原型:
flask.ext.login.login_user(user, remember=False, force=False, fresh=True)
登录表单时的模板
flasky/app/templates/auth/login.html
{% extends "base.html" %} {% import "bootstrap/wtf.html" as wtf %} {% block title %}Flasky - Login{% endblock %} {% block page_content %} <div class="page-header"> <h1>Login</h1> </div> ################################################ <div class="col-md-4"> {{ wtf.quick_form(form) }} </div> ###加入渲染的表单 ################################################ {% endblock %}
测试登录
flasky/app/templates/index.html
{% extends "base.html" %} {% block title %}Flasky{% endblock %} {% block page_content %} ##################################################### <div class="page-header"> <h1>Hello, {% if current_user.is_authenticated %}{{ current_user.username }}{% else %}Stranger{% endif %}!</h1> </div> ##################################################### ###用current._user.is_authenticated测试是否是登录的用户首页 {% endblock %}
此外,还有以下改动:
把之前main/views.py的各种复杂的储存用户会话消息name,判断是否是第一次输入,以及发送邮件等等去掉,简化成直接返回index.html模板。
flasky/app/main/views.py
from flask import render_template from . import main @main.route('/') def index(): return render_template('index.html')
flasky/migrations/versions/456a945560f6_login_support.py
数据库迁移脚本版本
"""login support Revision ID: 456a945560f6 Revises: 38c4e85512a9 Create Date: 2013-12-29 00:18:35.795259 """ # revision identifiers, used by Alembic. revision = '456a945560f6' down_revision = '38c4e85512a9' from alembic import op import sqlalchemy as sa def upgrade(): ### commands auto generated by Alembic - please adjust! ### op.add_column('users', sa.Column('email', sa.String(length=64), nullable=True)) op.add_column('users', sa.Column('password_hash', sa.String(length=128), nullable=True)) op.create_index('ix_users_email', 'users', ['email'], unique=True) ### end Alembic commands ### def downgrade(): ### commands auto generated by Alembic - please adjust! ### op.drop_index('ix_users_email', 'users') op.drop_column('users', 'password_hash') op.drop_column('users', 'email') ### end Alembic commands ###
flasky/requirements.txt
所有依赖包的文件
alembic==0.8.8 blinker==1.4 click==6.6 dominate==2.2.1 Flask==0.11.1 Flask-Bootstrap==3.3.7.0 Flask-Mail==0.9.1 Flask-Migrate==2.0.0 Flask-Moment==0.5.1 Flask-Script==2.0.5 Flask-SQLAlchemy==2.1 Flask-WTF==0.12 itsdangerous==0.24 Jinja2==2.8 Mako==1.0.4 MarkupSafe==0.23 python-editor==1.0.1 SQLAlchemy==1.0.15 visitor==0.1.3 Werkzeug==0.11.11 WTForms==2.1 Flask-Login==0.3.1 ###添加了flask-login包
相关文章推荐
- Spring Security笔记:使用数据库进行用户认证(form login using database) - 菩提树下的杨过 - 博客园
- 网站后端.Flask.实战-社交博客开发-flask-login认证用户?
- Spring Security笔记:使用数据库进行用户认证(form login using database)
- Spring Security笔记:使用数据库进行用户认证(form login using database)
- 让Sendmail和Dovecot使用AD进行用户认证
- 使用Login控件执行自定义认证
- [Subversion]使用密碼文件认证,添加新用户
- apache使用.htaccess文件实现用户认证
- mysql用户认证协议更换(mysql使用问题)
- 使用Java Mail Authenticator子类进行用户认证来发送电子邮件示例
- CentOS 5下搭建使用MySQL认证用户的POSTFIX邮件服务器
- 使用Handler来增强Web服务的功能(生成日志、用户认证、用户授权、信息加密/解密)
- DB2 9 使用启示(733 检验)认证指南,第 9 部分: 用户界说的例程(3)
- 配置Dotnetnuke使用AD用户认证
- [轉]使用sp_change_users_login修复产生的孤立账户& 还原中的孤立用户
- Borland CaliberRM/StarTeam 2005使用LDAP实现统一用户认证(二)
- 用wget使用认证用户从ftp站点下载文件
- CentOS 5下搭建使用MySQL认证用户的POSTFIX邮件服务器
- 使用 Zend_Auth 和 Zend_Db 实现用户认证(ZF Study)