目录

前文列表

用 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

  • 安装
  1. (env) [root@flask-dev JmilkFan-s-Blog]# pip install Flask-Bcrypt
  2. (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
  1. from flask.ext.bcrypt import Bcrypt
  2. # Create the Flask-Bcrypt's instance
  3. bcrypt = Bcrypt()

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

  • jmilkfansblog/__init__.py
  1. from flask import Flask, redirect, url_for
  2. from jmilkfansblog.models import db
  3. from jmilkfansblog.controllers import blog
  4. from jmilkfansblog.extensions import bcrypt
  5. def create_app(object_name):
  6. """Create the app instance via `Factory Method`"""
  7. app = Flask(__name__)
  8. # Set the config for app instance
  9. app.config.from_object(object_name)
  10. # Will be load the SQLALCHEMY_DATABASE_URL from config.py to db object
  11. db.init_app(app)
  12. # Init the Flask-Bcrypt via app object
  13. bcrypt.init_app(app)
  14. @app.route('/')
  15. def index():
  16. # Redirect the Request_url '/' to '/blog/'
  17. return redirect(url_for('blog.home'))
  18. # Register the Blueprint into app object
  19. app.register_blueprint(blog.blog_blueprint)
  20. return app
  • NOTE 2:模块中的导入路径最好使用绝对路径。

  • models.py

  1. from jmilkfansblog.extensions import bcrypt
  2. class User(db.Model):
  3. """Represents Proected users."""
  4. # Set the name for table
  5. __tablename__ = 'users'
  6. id = db.Column(db.String(45), primary_key=True)
  7. username = db.Column(db.String(255))
  8. password = db.Column(db.String(255))
  9. # one to many: User ==> Post
  10. # Establish contact with Post's ForeignKey: user_id
  11. posts = db.relationship(
  12. 'Post',
  13. backref='users',
  14. lazy='dynamic')
  15. def __init__(self, id, username, password):
  16. self.id = id
  17. self.username = username
  18. self.password = self.set_password(password)
  19. def __repr__(self):
  20. """Define the string format for instance of User."""
  21. return "<Model User `{}`>".format(self.username)
  22. def set_password(self, password):
  23. """Convert the password to cryptograph via flask-bcrypt"""
  24. return bcrypt.generate_password_hash(password)
  25. def check_password(self, password):
  26. return bcrypt.check_password_hash(self.password, password)
  • set_password(self, password):在设定密码的时候,将明文密码转换成为 Bcrypt 类型的哈希值。
  • check_password(self, password):检验输入的密码的哈希值,与存储在数据库中的哈希值是否一致。

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

创建登陆表单

  • forms.py
  1. from flask_wtf import Form
  2. from wtforms import (
  3. StringField,
  4. TextField,
  5. TextAreaField,
  6. PasswordField,
  7. BooleanField,
  8. ValidationError
  9. )
  10. from wtforms.validators import DataRequired, Length, EqualTo, URL
  11. from jmilkfansblog.models import User
  12. class LoginForm(Form):
  13. """Login Form"""
  14. username = StringField('Username', [DataRequired(), Length(max=255)])
  15. password = PasswordField('Password', [DataRequired()])
  16. def validate(self):
  17. """Validator for check the account information."""
  18. check_validata = super(LoginForm, self).validate()
  19. # If validator no pass
  20. if not check_validata:
  21. return False
  22. # Check the user whether exist.
  23. user = User.query.filter_by(username=self.username.data).first()
  24. if not user:
  25. self.username.errors.append('Invalid username or password.')
  26. return False
  27. # Check the password whether right.
  28. if not user.check_password(self.password.data):
  29. self.username.errors.append('Invalid username or password.')
  30. return False
  31. 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. ScoutSuite:一款针对云集群环境的安全审计工具

    工具介绍 Scout Suite是一款针对云集群环境的开源安全审计工具,主要针对的是云端环境的安全状况.通过使用云服务提供商暴露的API,Scout Suite可以从高安全风险区域收集配置数据以备研究 ...

  2. [Linux] 028 源码包安装过程

    1. 安装准备 安装 C 语言编译器 下载源码包 如:apache 相应源码包下载地址 2. 安装注意事项 源代码保存位置:/usr/local/src 软件安装位置:/usr/local 如何确定安 ...

  3. 《剑指offer》面试题10 二进制中1的个数 Java版

    书中方法一:对于每一位,用1求与,如果为1表明该位为1.一共要进行32次,int4字节32位. public int check(int a){ int result = 0; int judge = ...

  4. P3806 【模板】点分治1(题解)(点分治)

    P3806 [模板]点分治1(题解)(点分治) 洛谷题目传送门 #include<iostream> #include<cstdlib> #include<cstdio& ...

  5. MySQL 新建用户和数据库

    MySQL 新建用户和数据库 修改MySql的密码为qwe123 /usr/local/bin/mysqladmin -u root -p password qwe123 mysql设置root远程访 ...

  6. jsp常用代码

    1.头部 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8&q ...

  7. vue.js(09)--v-for中的key

    v-for中key的使用注意事项 <!DOCTYPE html> <html lang="en"> <head> <meta charse ...

  8. 本机ip地址怎么查

     转自:https://www.192ly.com/basic/local-ip-address-lookup-method.html 百度搜索一下[IP],你就可以轻松看到你的IP地址了,百度出来的 ...

  9. java String练习题

    package java07; /* 题目: 定义一个方法,把数组{1,2,3}按照指定格式拼接成一个字符串,格式参照如下:[word1#word2#word3] 思路: 1.首先准备一个int[]数 ...

  10. Echarts 折线类型

    1:Echarts2.0 这种皮肤下柱状图转折线图默认是平滑曲线 默认皮肤为硬折线: 如果需要在2.0的macarons皮肤下使用硬折线需显式设置以下属性:  series: [         { ...