zoukankan      html  css  js  c++  java
  • 【简说Python WEB】用户身份验证--Werkzeug

    系统环境:Ubuntu 18.04.1 LTS

    Python使用的是虚拟环境:virutalenv

    Python的版本:Python 3.6.9

    【简说Python WEB】用户身份验证--Werkzeug

    基本大多数web应用都有用户身份验证。

    基本的身份验证,要不是用户名,要不是电子邮件地址。加上自己的密码。完成身份验证。

    这里就是做一个完整的用户身份验证系统

    Flask的security扩展

    • FLask-Login:管理已经登录的用户会话
    • Werkzeug:计算密码散列值,同时进行check
    • itsdangerous:生成并check加密安全令牌

    使用Werkzeug生成密码散列值

    Werkzeug的security模块实现了散列值的计算。有两个函数,一个生成,另外一个核对

    如下:

    generate_password_hash(password,method='pbkdf2:sha256',salt_length=8)

    三个输入参数:

    • 第一个参数: 输入密码
    • 第二个参数:pbkdf2_sha256加密验证算法
    • 第三个参数:salt值字符串长度。

    pbkdf2_sha256 + SALT盐值加密,是很可靠的一种加密方式。

    输入的值是一个密码,输出的值返回密码散列值的字符串。基本默认值就够用了。

    check_password_hash(hash, password)

    这个参数从数据库中取出密码的hash值和输入的密码值进行校对。如果返回为True说明输入的密码正确。

    app/models.py加入Werkzeug密码散列值

    from werkzeug.security import generate_password_hash, check_password_hash
    class User(db.Model):
        #..
        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)
    

    在shell测试上述代码:

    (zsdpy1) zsd@zsd-virtual-machine:~/Zflask$ flask shell
    Python 3.6.9 (default, Nov  7 2019, 10:44:02) 
    [GCC 8.3.0] on linux
    App: app [production]
    Instance: /home/zsd/Zflask/instance
    >>> u = User()
    >>> u.password = 'cat' 
    >>> u.password_hash
    'pbkdf2:sha256:150000$bCVGWsku$752d59b87a450aac1b2ea9297e6475f2300fcdea4b589f788aa753e1a820c12d'
    >>> u.verify_password('cat')
    True
    >>> u.verify_password('zsd')
    False
    >>> u2 = User()
    >>> u2.password = 'cat'
    >>> u2.password_hash
    'pbkdf2:sha256:150000$oMmeJziP$92900571f3639e0dca770bbb94f83c64a22d3f510343446a32499c2f64783962'
    

    可以看到u和u2的密码虽然都是cat,但是hash密码值确实不一样的。

    这样手动写shell一步一步测试特别浪费时间,我们可以通过写单元测试,完成测试工作。如下:

    tests/test_user_model.py 密码散列测试

    import unittest
    from app import create_app, db
    from app.models import User
    
    
    class UserModelTestCase(unittest.TestCase):
        def setUp(self):
            self.app = create_app('testing')
            self.app_context = self.app.app_context()
            self.app_context.push()
            db.create_all()
    
        def tearDown(self):
            db.session.remove()
            db.drop_all()
            self.app_context.pop()
    
        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)
    

    执行下列命令,做单元测试 :

    (zsdpy1) $ flask test
    test_app_exists (test_basics.BasicsTestCase) ... ok
    test_app_is_testing (test_basics.BasicsTestCase) ... ok
    test_no_password_getter (test_user_model.UserModelTestCase) ... ok
    test_password_salts_are_random (test_user_model.UserModelTestCase) ... ok
    test_password_setter (test_user_model.UserModelTestCase) ... ok
    test_password_verification (test_user_model.UserModelTestCase) ... ok
    
    ----------------------------------------------------------------------
    Ran 6 tests in 2.760s
    

    这样就相当于自动化测试,直接测试了刚刚shell做得测试工作。

  • 相关阅读:
    jquery 动态选中radio
    在Struts2的Action中取得请求参数值的几种方法
    Collections类sort方法的用法
    struts2 action 之间跳转
    JavaScript 解析 xml 文件 如 rss订阅
    jquery 获取 选中的checkbox的值
    velocity 时间显示 时间格式化 时间转化
    firefox3.6 ie8 jQuery选择checkbox
    IFormattedTextSymbol接口 设定Anchor点的水平或者垂直对其方式
    gisbase网站,因其购买的空间提供商,“涉黄”暂行关闭。
  • 原文地址:https://www.cnblogs.com/zhangshengdong/p/12561678.html
Copyright © 2011-2022 走看看