码迷,mamicode.com
首页 > 其他好文 > 详细

10、密码扩展

时间:2019-11-03 12:42:24      阅读:76      评论:0      收藏:0      [点我收藏+]

标签:blueprint   服务   文件   random   路径   程序模板   property   word   case   

1、使用Werkzeug实现密码散列

在User模型中加入密码散列

app/models.py 

计算密码散列值的函数通过名为password的只写属性实现,设定这个属性的值时,赋值方法会调用Werkzeug提供的generate_password_hash()函数,并把得到的结果赋值给password_hash字段。

如果试图读取password属性的值,则会返回错误,原因很明显,因为生成散列值后就无法还原成原来的密码了

from . import db
from werkzeug.security import generate_password_hash, check_password_hash

#定义数据库模型
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)

    def __repr__(self):
        return <Role %r> %self.name


class User(db.Model):
    __tablename__ = users
    id = db.Column(db.Integer, primary_key=True)
    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))

    #在User模型中加入密码散列
    @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

在shell中验证加入的密码散列功能

注:u1,u2即使使用了相同的密码,它们的密码散列值也完全不一样

技术图片

 

把上述测试写成单元测试,以便于重复执行,我们在test包中新建一个模块,编写3个新测试,测试最近对User模型所做的修改

tests/test_user_model.py

import unittest
from app.models import User

#密码散列化测试

class UserModelTestCase(unittest.TestCase):
    def test_password_setter(self):
        u = User(password = cat)
        self.assertTrue(u.password_hash is not None)

    def test_no_password_getter(self):
        u = User(password = cat)
        with self.assertRaises(AttributeError):
            u.password

    def test_password_verification(self):
        u = User(password = cat)
        self.assertTrue(u.verify_password(cat))
        self.assertFalse(u.verify_password(dog))

    def test_password_salts_are_random(self):
        u = User(password = cat)
        u2 = User(password = cat)
        self.assertTrue(u.password_hash != u2.password_hash)

 

 2、创建认证蓝本

创建蓝本

app/auth/__init__.py  

app/auth/views.py模块引入蓝本,然后使用蓝本的route修饰器定义与认证相关的路由

from flask import Blueprint

#创建认证蓝本
auth = Blueprint(auth, __name__)

from . import views

 

蓝本中的路由和视图函数

app/auth/views.py

添加一个/login路由,渲染同名占位模板

render_template()指定的模板文件保存在auth文件夹中,这个文件夹必须在app/templates中创建,因为Flask认为模板的路径是相对于程序模板文件夹而言的。

为避免与main蓝本和后序添加的蓝本发生模板命名冲突,可以把蓝本使用的模板保存在单独的文件夹中

from flask import render_template
from . import auth

#蓝本中的路由和视图函数
@auth.route(/login)
def login():
    return render_template(auth/login.html)

 

附加蓝本

app/__init__.py

url_prefix是可选参数,使用这个参数后,注册蓝本中定义的所有路由都会加上指定的前缀,本例中,/login路由会注册成/auth/login,在web服务器中,完整的URL就变成了http://locahost:5000/auth/login

from flask import Flask, render_template
from flask_bootstrap import Bootstrap
from flask_mail import Mail
from flask_moment import Moment
from flask_sqlalchemy import SQLAlchemy
from config import config

bootstrap = Bootstrap()
mail = Mail()
moment = Moment()
db = SQLAlchemy()

def create_app(config_name):
    app = Flask(__name__)
    app.config.from_object(config[default])
    config[default].init_app(app)

    bootstrap.init_app(app)
    mail.init_app(app)
    moment.init_app(app)
    db.init_app(app)

    #认证函数的附加蓝本
    from .auth import auth as auth_blueprint
    app.register_blueprint(auth_blueprint, url_prefix=/auth)

    from .main import main as main_blueprint
    app.register_blueprint(main_blueprint)

    #附加路由和自定义的错误页面

    return app

 

10、密码扩展

标签:blueprint   服务   文件   random   路径   程序模板   property   word   case   

原文地址:https://www.cnblogs.com/lw-monster/p/11785676.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!