学会了如何创建用户登录表单及运用数据库。现在教你如何结合这两章的主题来创建一个简单的用户登录系统。

一、User模型中的密码哈希值

用户模型设置了一个password_hash字段, 这个字段的目的是保存用户密码的哈希值,并用于验证用户在登录过程中输入的密码。 密码哈希的实现是一个复杂的话题,应该由安全专家来搞定,不过,已经有数个现成的简单易用且功能完备加密库存在了。其中一个实现密码哈希的包是Werkzeug,当安装Flask时,你可能会在pip的输出中看到这个包,因为它是Flask的一个核心依赖项。 所以,Werkzeug已经安装在你的虚拟环境中。

验证一下:

from werkzeug.security import generate_password_hash
hash=generate_password_hash('hash_worth')
hash
'pbkdf2:sha256:260000$42OZBYPD3gasP8Dp$b322f885bef0e6a16d92763441361238d99e8d2dfe03f926455915fccb6dda62'
from werkzeug.security import check_password_hash
check_password_hash(hash,'password')
False
check_password_hash(hash,'hash_worth')
True

可以在用户模型中实现为两个新的方法:

from werkzeug.security import generate_password_hash, check_password_hash
# ...
class User(db.Model):# ...def set_password(self, password):self.password_hash = generate_password_hash(password)def check_password(self, password):return check_password_hash(self.password_hash, password)

使用这两种方法,用户对象现在可以在无需持久化存储原始密码的条件下执行安全的密码验证。 以下是这些新方法的示例用法:

>>> u=User(username='susan',email='susan@mail.com')
>>> u.set_password('password')
>>> u.check_password('password')
True
>>> u.check_password('pass')
False
>>>

二、Flask_login扩展的应用

该插件管理用户登录状态,以便用户可以登录到应用,然后用户在导航到该应用的其他页面时,应用会“记得”该用户已经登录。它还提供了“记住我”的功能,允许用户在关闭浏览器窗口后再次访问应用时保持登录状态。可以先在你的虚拟环境中安装Flask-Login来做好准备工作:

(microblog) D:\pythonProgram\PycharmProjects\microblog>pip install flask-login
Collecting flask-loginUsing cached Flask_Login-0.5.0-py2.py3-none-any.whl (16 kB)
Requirement already satisfied: Flask in d:\pycharmprojects\flask\microblog\lib\site-packages (from flask-login) (2.0.1)
Requirement already satisfied: Jinja2>=3.0 in d:\pycharmprojects\flask\microblog\lib\site-packages (from Flask->flask-login) (3.0.1)
Requirement already satisfied: Werkzeug>=2.0 in d:\pycharmprojects\flask\microblog\lib\site-packages (from Flask->flask-login) (2.0.1)
Requirement already satisfied: click>=7.1.2 in d:\pycharmprojects\flask\microblog\lib\site-packages (from Flask->flask-login) (8.0.1)
Requirement already satisfied: itsdangerous>=2.0 in d:\pycharmprojects\flask\microblog\lib\site-packages (from Flask->flask-login) (2.0.1)
Requirement already satisfied: colorama in d:\pycharmprojects\flask\microblog\lib\site-packages (from click>=7.1.2->Flask->flask-login) (0.4.4)
Requirement already satisfied: MarkupSafe>=2.0 in d:\pycharmprojects\flask\microblog\lib\site-packages (from Jinja2>=3.0->Flask->flask-login) (2.0.1)
Installing collected packages: flask-login
Successfully installed flask-login-0.5.0

和其他插件一样,Flask-Login需要在app/__init__py中的应用实例之后被创建和初始化。

# ...
from flask_login import LoginManagerapp = Flask(__name__)
# ...
login = LoginManager(app)# ...

准备用户模型

Flask-Login插件需要在用户模型上实现某些属性和方法。必须的四项如下:

  1. is_authenticated: 一个用来表示用户是否通过登录认证的属性,用True和False表示。
  2. is_active: 如果用户账户是活跃的,那么这个属性是True,否则就是False(译者注:活跃用户的定义是该用户的登录状态是否通过用户名密码登录,通过“记住我”功能保持登录状态的用户是非活跃的)。
  3. is_anonymous: 常规用户的该属性是False,对特定的匿名用户是True。
  4. get_id():返回用户的唯一id的方法,返回值类型是字符串(Python 2下返回unicode字符串).

Flask-Login提供了一个叫做UserMixin的mixin类来将它们归纳其中。 下面演示了如何将mixin类添加到模型中:

# ...
from flask_login import UserMixinclass User(UserMixin, db.Model):# ...

用户加载函数

flask-login通过调用session内存储的用户ID来识别用户,基于此,应用需配置一个用户加载函数,可以调用该函数来加载给定ID的用户。 该功能可以添加到app/models.py模块中:

from app import login
# ...@login.user_loader
def load_user(id):return User.query.get(int(id))

三、用户登入及登出函数

用户登入视图函数

# ...
from flask_login import current_user, login_user
from app.models import User# ...@app.route('/login', methods=['GET', 'POST'])
def login():if current_user.is_authenticated:return redirect(url_for('index'))form = LoginForm()if form.validate_on_submit():user = User.query.filter_by(username=form.username.data).first()if user is None or not user.check_password(form.password.data):flash('Invalid username or password')return redirect(url_for('login'))login_user(user, remember=form.remember_me.data)return redirect(url_for('index'))return render_template('login.html', title='Sign In', form=form)

用户登出视图函数

# ...
from flask_login import logout_user# ...@app.route('/logout')
def logout():logout_user()return redirect(url_for('index'))

导航栏上实现当用户登录之后,登录链接自动转换成登出链接。修改base.html模板的导航栏部分后,代码如下:

<div>Microblog:<a href="{{ url_for('index') }}">Home</a>{% if current_user.is_anonymous %}<a href="{{ url_for('login') }}">Login</a>{% else %}<a href="{{ url_for('logout') }}">Logout</a>{% endif %}</div>

要求用户登录

Flask-Login提供了一个非常有用的功能——强制用户在查看应用的特定页面之前登录。 如果未登录的用户尝试查看受保护的页面,Flask-Login将自动将用户重定向到登录表单,并且只有在登录成功后才重定向到用户想查看的页面。
为了实现这个功能,Flask-Login需要知道哪个视图函数用于处理登录认证。在app/init.py中添加代码如下:

# ...
login = LoginManager(app)
login.login_view = 'login' #'login'值是登录视图函数(endpoint)名

Flask-Login使用名为@login_required的装饰器来拒绝匿名用户的访问以保护某个视图函数。 当你将此装饰器添加到位于@app.route装饰器下面的视图函数上时,该函数将受到保护,不允许未经身份验证的用户访问。 以下是该装饰器如何应用于应用的主页视图函数的案例:

from flask_login import login_required@app.route('/')
@app.route('/index')
@login_required
def index():# ...

剩下的就是实现登录成功之后自定重定向回到用户之前想要访问的页面。 当一个没有登录的用户访问被@login_required装饰器保护的视图函数时,装饰器将重定向到登录页面,不过,它将在这个重定向中包含一些额外的信息以便登录后的回转。 例如,如果用户导航到/index,那么@login_required装饰器将拦截请求并以重定向到/login来响应,但是它会添加一个查询字符串参数来丰富这个URL,如/login?next=/index。 原始URL设置了next查询字符串参数后,应用就可以在登录后使用它来重定向。
下面是一段代码,展示了如何读取和处理next查询字符串参数:

from flask import request
from werkzeug.urls import url_parse@app.route('/login', methods=['GET', 'POST'])
def login():# ...if form.validate_on_submit():user = User.query.filter_by(username=form.username.data).first()if user is None or not user.check_password(form.password.data):flash('Invalid username or password')return redirect(url_for('login'))login_user(user, remember=form.remember_me.data)next_page = request.args.get('next')if not next_page or url_parse(next_page).netloc != '':next_page = url_for('index')return redirect(next_page)# ...

在模板中显示已登录的用户

{% extends "base.html" %}{% block content %}<h1>Hi, {{ current_user.username }}!</h1>{% for post in posts %}<div><p>{{ post.author.username }} says: <b>{{ post.body }}</b></p></div>{% endfor %}
{% endblock %}

视图函数传入渲染模板函数的参数中删除user

@app.route('/')
@app.route('/index')
def index():# ...return render_template("index.html", title='Home Page', posts=posts)

添加用户到数据库的唯一方法是通过Python shell执行,所以运行flask shell并输入以下命令来注册用户:

(microblog) D:\pythonProgram\PycharmProjects\microblog>flask shell
Python 3.8.5 (tags/v3.8.5:580fbb0, Jul 20 2020, 15:57:54) [MSC v.1924 64 bit (AMD64)] on win32
App: app [production]
Instance: D:\pythonProgram\PycharmProjects\microblog\instance
>>> u=User(username='susan',email='susan@mail.com')
>>> u.set_password('pass')
>>> db.session.add(u)
>>> db.session.commit()

启动应用并尝试访问 http://localhost:5000/ 或 http://localhost:5000/index ,会立即重定向到登录页面。在使用之前添加到数据库的凭据登录后,就会跳转回到之前访问的页面,并看到其中的个性化欢迎。

四、用户注册

在app/forms.py中创建Web表单类:

from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, SubmitField
from wtforms.validators import ValidationError, DataRequired, Email, EqualTo
from app.models import User# ...class RegistrationForm(FlaskForm):username = StringField('Username', validators=[DataRequired()])email = StringField('Email', validators=[DataRequired(), Email()])password = PasswordField('Password', validators=[DataRequired()])password2 = PasswordField('Repeat Password', validators=[DataRequired(), EqualTo('password')])submit = SubmitField('Register')def validate_username(self, username):user = User.query.filter_by(username=username.data).first()if user is not None:raise ValidationError('Please use a different username.')def validate_email(self, email):user = User.query.filter_by(email=email.data).first()if user is not None:raise ValidationError('Please use a different email address.')

需要一个

HTML模板

以便在网页上显示这个表单,存储在app/templates/register.html文件中。 这个模板的构造与登录表单类似:

{% extends "base.html" %}{% block content %}<h1>Register</h1><form action="" method="post">{{ form.hidden_tag() }}<p>{{ form.username.label }}<br>{{ form.username(size=32) }}<br>{% for error in form.username.errors %}<span style="color: red;">[{{ error }}]</span>{% endfor %}</p><p>{{ form.email.label }}<br>{{ form.email(size=64) }}<br>{% for error in form.email.errors %}<span style="color: red;">[{{ error }}]</span>{% endfor %}</p><p>{{ form.password.label }}<br>{{ form.password(size=32) }}<br>{% for error in form.password.errors %}<span style="color: red;">[{{ error }}]</span>{% endfor %}</p><p>{{ form.password2.label }}<br>{{ form.password2(size=32) }}<br>{% for error in form.password2.errors %}<span style="color: red;">[{{ error }}]</span>{% endfor %}</p><p>{{ form.submit() }}</p></form>
{% endblock %}

登录表单模板需要在其表单之下添加一个链接来将未注册的用户引导到注册页面:

<p>New User? <a href="{{ url_for('register') }}">Click to Register!</a></p>

实现处理

用户注册的视图函数

,存储在app/routes.py中,代码如下:

from app import db
from app.forms import RegistrationForm# ...@app.route('/register', methods=['GET', 'POST'])
def register():if current_user.is_authenticated:return redirect(url_for('index'))form = RegistrationForm()if form.validate_on_submit():user = User(username=form.username.data, email=form.email.data)user.set_password(form.password.data)db.session.add(user)db.session.commit()flash('Congratulations, you are now a registered user!')return redirect(url_for('login'))return render_template('register.html', title='Register', form=form)

精雕细琢之后,用户已经能够在此应用上注册帐户,并进行登录和注销。

Study_microblog笔记Part 5--用户登录相关推荐

  1. Linux学习笔记(四)之用户登录

    1.Linux是一个网络操作系统,作为多用户,多任务的操作系统,其系统资源是所有用户共享的.任何要使用系统资源者必须先在系统内登记,注册,即开设用户账号,该账号又包含用户名,口令,所用的shell,使 ...

  2. 尚硅谷谷粒学院学习笔记9--前台用户登录,注册,整合jwt,微信登录

    用户登录业务 单点登录(Single Sign On),简称SSO. 用户只需要登陆一次就可以访问所有相互信任的应用系统 单点登录三种常见方式 session广播机制实现 使用redis+cookie ...

  3. 华为云计算IE面试笔记-桌面云用户登录连接流程及故障处理

    1-10:桌面与系统验证成功                           http协议 11-19:桌面list(VM列表)获取,选择                http协议 20-30: ...

  4. sqlplus普通用户登录oracle,Oracle学习笔记:sqlplus用户登录

    1 sqlplus 登录 本地登录 (登录数据库服务器) Oracle 登录 sqlplus 账户名/密码 as 角色名 1.1 sys登录 例如: sqlplus sys/or 1 sqlplus ...

  5. oracle 触发器登录,【学习笔记】Oracle触发器 实现指定用户登录oracle案例

    天萃荷净 触发器实现指定用户登录oracle,分享一篇关于Oracle数据库安全策略,通过Oracle触发器实现限定user用户登录Oracle数据库的方法 1.创建允许登录用户表 CREATE TA ...

  6. Vue + Spring Boot 学习笔记02:引入数据库实现用户登录功能

    Vue + Spring Boot 学习笔记02:引入数据库实现用户登录功能 在学习笔记01里,我们利用跨域打通了前端的Vue与后端的Spring Boot,实现了用户登录功能,但是后台的登录控制器在 ...

  7. Vue + Spring Boot 学习笔记01:实现用户登录功能

    Vue + Spring Boot 学习笔记01:实现用户登录功能 一.创建后端Spring Boot项目Book Management 二.创建前端Vue项目bm-vue 三.修改后端项目Book ...

  8. [go学习笔记.第十六章.TCP编程] 3.项目-海量用户即时通讯系统-redis介入,用户登录,注册

    1.实现功能-完成用户登录 在redis手动添加测试用户,并画出示意图以及说明注意事项(后续通过程序注册用户) 如:输入用户名和密码,如果在redis中存在并正确,则登录,否则退出系统,并给出相应提示 ...

  9. C#笔记(学生管理系统实战 - 用户登录)

    总算忙过一段时间了,两个月前看了一点点关于 C# 的实战视频,现在看回来居然忘得七七八八,果然学习还是要写笔记,好记性不如烂笔头.. 1 项目框架 用户界面模块 数据访问模块 DAL(即如同 Serv ...

最新文章

  1. ARM Linux (S3C6410架构/2.6.35内核)的内存映射(三)
  2. Android移动开发之【Android实战项目】漂亮Button样式
  3. linux服务器centos系统apache路径不区分大小写的解决办法(适用WDCP面板)
  4. Angular数据绑定的学习笔记
  5. python编程小案例_用Python3编程写第一个小案例!-Go语言中文社区
  6. 嵌入式根文件系统的移植和制作详解
  7. Web前端框架(JavaScript,CSS)、html组件、CSS规范与第三方库
  8. redis技术分享ppt_精美PPT制作培训 | 技术二部内部分享
  9. 2021年9月再次更新-日立电梯,艾默生变频器维修图纸,原理图
  10. CEF加载PPAPI插件
  11. c语言卡诺图算法实现,多变量卡诺图化简的算法实现.pdf
  12. 3D建模和渲染的硬件配置怎么选?这里有答案
  13. 分布式 | 如何与 DBLE 进行“秘密通话”
  14. 我的python中级班学习之路(全程笔记第一模块) (第二章)(第3部分:元祖、哈希(hash)、字典、集合...
  15. 优秀课程案例:母亲节!用Scratch编程送给母亲最好的贺卡礼物!
  16. echarts实现自定义扩展地图-中国七大区域图
  17. 在线YAML转Properties工具
  18. [渗透测试学习靶机03] vulnhub靶场 Empire LupinOne
  19. Redy语法分析--抽象语法树简介
  20. postgresql查询锁表以及解除锁表

热门文章

  1. Q版程序员系列表情包
  2. Vue实现父子组件页面刷新的常用方法
  3. xlsx表格怎么做汇总统计_怎样在excel电子表格中对数据进行分类汇总,实例教程...
  4. 用python摘取汇总多个txt文件关键信息汇总写入excel
  5. [转载]Qt platform plugin 'windows'
  6. python 数据判断利润表计算
  7. Java程序的下载安装
  8. 免密码登录oracle,Oracle Cloud云主机:Xshell配置ssh免密码登录-密钥公钥(Public key)
  9. 「GoTeam 招聘时间」容联云 Go运维开发(武汉)
  10. 我叫mt4服务器维护时间,我叫mt4日常几点更新?日常任务刷新时间介绍[图]