目录

前文列表

用 Flask 来写个轻博客 (1) — 创建项目

用 Flask 来写个轻博客 (2) — Hello World!

用 Flask 来写个轻博客 (3) — (M)VC_连接 MySQL 和 SQLAlchemy

用 Flask 来写个轻博客 (4) — (M)VC_创建数据模型和表

用 Flask 来写个轻博客 (5) — (M)VC_SQLAlchemy 的 CRUD 详解

用 Flask 来写个轻博客 (6) — (M)VC_models 的关系(one to many)

用 Flask 来写个轻博客 (7) — (M)VC_models 的关系(many to many)

用 Flask 来写个轻博客 (8) — (M)VC_Alembic 管理数据库结构的升级和降级

用 Flask 来写个轻博客 (9) — M(V)C_Jinja 语法基础快速概览

用 Flask 来写个轻博客 (10) — M(V)C_Jinja 常用过滤器与 Flask 特殊变量及方法

用 Flask 来写个轻博客 (11) — M(V)C_创建视图函数

用 Flask 来写个轻博客 (12) — M(V)C_编写和继承 Jinja 模板

用 Flask 来写个轻博客 (13) — M(V)C_WTForms 服务端表单检验

用 Flask 来写个轻博客 (14) — M(V)C_实现项目首页的模板

用 Flask 来写个轻博客 (15) — M(V)C_实现博文页面评论表单

用 Flask 来写个轻博客 (16) — MV(C)_Flask Blueprint 蓝图

用 Flask 来写个轻博客 (17) — MV(C)_应用蓝图来重构项目

用 Flask 来写个轻博客 (18) — 使用工厂模式来生成应用对象

修改 User Model

使用明文的方式存储账户数据是一个非常严重的安全隐患,要保护用户的密码,就要使用 哈希算法的单向加密方法

哈希算法:对于相同的数据,哈希算法总是会生成相同的结果。

单向加密:就是信息在加密之后,其原始信息是不可能通过密文反向计算出来的。

所以,为了账户信息的安全,在数据库中存储的密码应该是被哈希过的哈希值。但是需要注意,哈希算法的种类很多,其中大多是是不安全的,可以被黑客 暴力破解

暴力破解:通过遍历各种数据的哈希值,来找到匹配的哈希值,从而获取你的密码权限。

所以这里我们使用 Bcrypt 哈希算法,这是一种被刻意设计成抵消且缓慢的哈希计算方式,从而极大的加长了暴力破解的时间和成本,以此来保证安全性。

Flask Bcrypt

  • 安装
(env) [root@flask-dev JmilkFan-s-Blog]# pip install Flask-Bcrypt
(env) [root@flask-dev JmilkFan-s-Blog]# pip freeze > requirements.txt

NOTE: Flask Bcrypt 与 Flask SQLAlchemy 一样需要使用 app 对象来进行初始化,我们在 jmilkfansblog 目录下新建一个 extensions.py 来实现我们以后会使用到的所有 Flask 扩展。

将 Bcrypt 应用到 User Model 中

  • extensions.py
from flask.ext.bcrypt import Bcrypt

# Create the Flask-Bcrypt's instance
bcrypt = Bcrypt()

NOTE 1:以后所有会使用到的 Flask 扩展都会在 extensions.py 中。

  • jmilkfansblog/__init__.py
from flask import Flask, redirect, url_for

from jmilkfansblog.models import db
from jmilkfansblog.controllers import blog
from jmilkfansblog.extensions import bcrypt def create_app(object_name):
"""Create the app instance via `Factory Method`""" app = Flask(__name__)
# Set the config for app instance
app.config.from_object(object_name) # Will be load the SQLALCHEMY_DATABASE_URL from config.py to db object
db.init_app(app)
# Init the Flask-Bcrypt via app object
bcrypt.init_app(app) @app.route('/')
def index():
# Redirect the Request_url '/' to '/blog/'
return redirect(url_for('blog.home')) # Register the Blueprint into app object
app.register_blueprint(blog.blog_blueprint) return app
  • NOTE 2:模块中的导入路径最好使用绝对路径。

  • models.py

from jmilkfansblog.extensions import bcrypt

class User(db.Model):
"""Represents Proected users.""" # Set the name for table
__tablename__ = 'users'
id = db.Column(db.String(45), primary_key=True)
username = db.Column(db.String(255))
password = db.Column(db.String(255))
# one to many: User ==> Post
# Establish contact with Post's ForeignKey: user_id
posts = db.relationship(
'Post',
backref='users',
lazy='dynamic') def __init__(self, id, username, password):
self.id = id
self.username = username
self.password = self.set_password(password) def __repr__(self):
"""Define the string format for instance of User."""
return "<Model User `{}`>".format(self.username) def set_password(self, password):
"""Convert the password to cryptograph via flask-bcrypt"""
return bcrypt.generate_password_hash(password) def check_password(self, password):
return bcrypt.check_password_hash(self.password, password)
  • set_password(self, password):在设定密码的时候,将明文密码转换成为 Bcrypt 类型的哈希值。
  • check_password(self, password):检验输入的密码的哈希值,与存储在数据库中的哈希值是否一致。

    • 验证
>>> from uuid import uuid4
>>> user = User(id=str(uuid4()), username='test_1', password='fanguiju')
>>> db.session.add(user)
>>> db.session.commit()
>>>
>>>
>>> user = User.query.filter_by(username='test_1').first()
>>> user.password
u'$2b$12$omKgt8saJydyfbBYwMnms.1ihw7Ox6alBPKdYsPUKtzaBQaNM4Guy'

创建登陆表单

  • forms.py
from flask_wtf import Form
from wtforms import (
StringField,
TextField,
TextAreaField,
PasswordField,
BooleanField,
ValidationError
)
from wtforms.validators import DataRequired, Length, EqualTo, URL from jmilkfansblog.models import User class LoginForm(Form):
"""Login Form""" username = StringField('Username', [DataRequired(), Length(max=255)])
password = PasswordField('Password', [DataRequired()]) def validate(self):
"""Validator for check the account information."""
check_validata = super(LoginForm, self).validate() # If validator no pass
if not check_validata:
return False # Check the user whether exist.
user = User.query.filter_by(username=self.username.data).first()
if not user:
self.username.errors.append('Invalid username or password.')
return False # Check the password whether right.
if not user.check_password(self.password.data):
self.username.errors.append('Invalid username or password.')
return False return True
  • NOTE 1: LoginForm 重载的 validate() 中调用了父类 Form 中的 validate(),用于检验用户输入的数据是否通过了 username/password 字段的检验器。
  • NOTE 2:LoginForm 重载的 validate() 不仅仅实现了父类的功能,还实现了检验 username 是否存在和用户输入的 password 是否正确的功能。子类重载父类的方法结合 super() 内置函数是 Python OOP 中常用的技巧

用 Flask 来写个轻博客 (19) — 以 Bcrypt 密文存储账户信息与实现用户登陆表单的更多相关文章

  1. 用 Flask 来写个轻博客

    用 Flask 来写个轻博客 用 Flask 来写个轻博客 (1) — 创建项目 用 Flask 来写个轻博客 (2) — Hello World! 用 Flask 来写个轻博客 (3) — (M)V ...

  2. 用 Flask 来写个轻博客 (37) — 在 Github 上为第一阶段的版本打 Tag

    Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 第一阶段结语 打 Tag 前文列表 用 Flask 来写个轻博客 (1 ...

  3. 用 Flask 来写个轻博客 (36) — 使用 Flask-RESTful 来构建 RESTful API 之五

    目录 目录 前文列表 PUT 请求 DELETE 请求 测试 对一条已经存在的 posts 记录进行 update 操作 删除一条记录 前文列表 用 Flask 来写个轻博客 (1) - 创建项目 用 ...

  4. 用 Flask 来写个轻博客 (35) — 使用 Flask-RESTful 来构建 RESTful API 之四

    Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 POST 请求 身份认证 测试 前文列表 用 Flask 来写个轻博客 ...

  5. 用 Flask 来写个轻博客 (34) — 使用 Flask-RESTful 来构建 RESTful API 之三

    目录 目录 前文列表 应用请求中的参数实现 API 分页 测试 前文列表 用 Flask 来写个轻博客 (1) - 创建项目 用 Flask 来写个轻博客 (2) - Hello World! 用 F ...

  6. 用 Flask 来写个轻博客 (33) — 使用 Flask-RESTful 来构建 RESTful API 之二

    Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 扩展阅读 构建 RESTful Flask API 定义资源路由 格式 ...

  7. 用 Flask 来写个轻博客 (32) — 使用 Flask-RESTful 来构建 RESTful API 之一

    目录 目录 前文列表 扩展阅读 RESTful API REST 原则 无状态原则 面向资源 RESTful API 的优势 REST 约束 前文列表 用 Flask 来写个轻博客 (1) - 创建项 ...

  8. 用 Flask 来写个轻博客 (31) — 使用 Flask-Admin 实现 FileSystem 管理

    Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 扩展阅读 编写 FileSystem Admin 页面 Flask-A ...

  9. 用 Flask 来写个轻博客 (30) — 使用 Flask-Admin 增强文章管理功能

    Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 扩展阅读 实现文章管理功能 实现效果 前文列表 用 Flask 来写个 ...

随机推荐

  1. python的tesseract库几个重要的命令

    在调用tesseract时,最重要的三个参数是 -l, -oem 和 -psm -l 参数控制识别文本的语言.可以通过命令 tesseract --list-langs  查看已经安装的字库. 支持中 ...

  2. 高级软件工程第二次作业:随机生成N个不重复的已解答完毕的数独棋盘

    #include <stdio.h> #include "SuduCheck.h" ][],int i,int j,int k) //判断是否可以将第i行.第j列的数设 ...

  3. [Linux] 012 文件搜索命令

    文件搜索命令:find 命令名称:find 命令所在路径:/bin/find 执行权限:所有用户 语法:find [搜索范围] [匹配条件] 功能描述:文件搜索 范例: 在目录 /etc 中查找文件 ...

  4. webpack4.0.1的坑

    webpack4在2月底正式发布后,原来的很多做法不能使用,下面把使用webpack4.0.1过程中,出现的问题,一一记录,也欢迎大家补充,谢谢!团结就是力量,众人拾柴火焰高,加油! 关于webpac ...

  5. python 模块和包深度学习理解

    python 模块和包 简单说相当于命名空间 1,python 模块        python模块就是一个文件,里面有函数,变量等 import 模块 模块.方法 from 模块 import fu ...

  6. git 命令图解

    git 命令图解   初始化版本库 git config user.name "lsgx" git config user.email "lsgxthink@163.co ...

  7. [三下五除二]在Eclipse上的JFinal_Demo

    承接上回在IDEA的JFinal的项目的导入,今次同样是同一个文件,但在Eclipse上运行.在Eclipse上运行官网的JFinal的例子是及其快捷. 打开Eclipse,并进入如下的界面. 点击导 ...

  8. This program cannot be run in DOS mode.

    问题:通过ftp上传的exe执行时提示“This program cannot be run in DOS mode.” 解决方法:检查ftp传输模式,设置成binary模式上传即可 参考:https ...

  9. procixx 时钟的坑

    error 1.procixx设置800M,uboot中是720M 了解到整个过程是,当procixx配置后,通过FSBL中的ps_init.c反应出来 // ARM_PLL_FDIV = 48    ...

  10. ThreadLocal的原理

    ThreadLocal是一个支持泛型的java类,抛开里面的静态内部类ThreadLocalMap不说,其实它没几行代码,不信,您自己去看看.它用来干啥?类上注释说的很明白: 它能让线程拥有了自己内部 ...