详解Python中的自定义密码验证

作者:Python是世界上最好的语言 时间:2021-06-05 00:38:59 

这些帖子将分为三个部分。

1.密码验证功能

2.重构密码验证函数

3.对密码验证功能进行单元测试

这是Python系列中自定义密码验证的第三部分,也是最后一部分。我们将看看对密码验证功能进行单元测试 .

下面是重构后的代码:

from string import (
   ascii_lowercase, ascii_uppercase,
   digits, punctuation, whitespace)

def contains_character(password: str = "", sack: str = "") -> bool:
   has_char = False
   for char in password:
       if char in sack:
           has_char = True
           break
   return has_char

def is_valid_size(password: str = "") -> bool:
   MIN_SIZE = 6
   MAX_SIZE = 20
   password_size = len(password)

return MIN_SIZE <= password_size <= MAX_SIZE

def get_invalid_chars():
   valid_chars = {'-', '_', '.', '!', '@', '#', '$', '^', '&', '(', ')'}
   invalid_chars = set(punctuation + whitespace) - valid_chars

return "".join(invalid_chars)

def is_valid_password(password: str = "") -> bool:
   try:
       if not password:
           return False

new_password = password.strip()

if not is_valid_size(new_password):
           return False

invalid_chars = get_invalid_chars()

if contains_character(new_password, invalid_chars):
           return False

if not contains_character(new_password, digits):
           return False

if not contains_character(new_password, ascii_lowercase):
           return False

if not contains_character(new_password, ascii_uppercase):
           return False

return True
   except:
       return False

我们的目标是为上面的代码片段编写单元测试。我们可以捕捉隐藏的错误,并在修复代码以通过测试时继续重构。

在测试:nut_and_bolt:️之前

有些事你应该知道:

  • 这将是一个单元测试

  • 我们将利用python的内置测试模块,unittest

  • 我们将测试,contains_character , is_valid_size和is_valid_password整齐

  • 测试将在test.py所以上面的片段可能在app.py(你选择你想要的名字)

  • 我们将参考

试验contains_character

contains_character返回bool,要么True或者False。所以我们可以使用assertTrue还有assertFalse方法。

我们将测试:

  • 如果既没有传递密码也没有传递sack(无参数)

  • 为了角色"i"在字符串中,"python"

  • 为了角色"py"在字符串中,"python"

  • 为了角色"python"在字符串中,"python"

有些情况下,比如int作为传递password或者当一个list作为传递sack。我们不会测试这种情况。(您应该为此进行测试)

TestContainsCharacter字符

import unittest
from app import contains_character

class TestContainsCharacter(unittest.TestCase):
   def test_empty_password_or_and_empty_sack(self):
       self.assertFalse(contains_character())

def test_char_i_in_str_python(self):
       self.assertFalse(contains_character("i", "python"))

def test_str_py_in_str_python(self):
       self.assertTrue(contains_character("py", "python"))

def test_str_python_in_str_python(self):
       self.assertTrue(contains_character("python", "python"))

if __name__ == "__main__":
   unittest.main()

我们能击中ctrl + F5运行此脚本(test.py)无需调试。我们可以像下面这样运行这个脚本python3 test.py或者python3 -m unittest test.py。所有这些测试都应该通过。

试验is_valid_size

is_valid_size返回bool,要么True或者False。所以我们可以使用assertTrue还有assertFalse方法。

我们将测试:

  • 对于空密码或没有传递参数时

  • 四个字符的密码

  • 六个字符的密码

  • 十六个字符的密码

  • 二十个字符的密码

  • 21个字符的密码

TestIsValidSize

import unittest
from app import is_valid_size

class TestIsValidSize(unittest.TestCase):
   def test_empty_password(self):
       self.assertFalse(is_valid_size(""))

def test_4_char_password(self):
       self.assertFalse(is_valid_size("pass"))

def test_6_char_password(self):
       self.assertTrue(is_valid_size("passwd"))

def test_16_char_password(self):
       self.assertTrue(is_valid_size("ThisIs1Password!"))

def test_20_char_password(self):
       self.assertTrue(is_valid_size("ThisIs1Password!+20"))

def test_21_char_password(self):
       self.assertFalse(is_valid_size("ThisIs1Password!+20&"))

if __name__ == "__main__":
   unittest.main()

所有这些测试都应该通过。

试验is_valid_password

is_valid_password返回bool,要么True或者False。所以我们可以使用assertTrue还有assertFalse方法。

我们将测试:

1.对于空密码

2.三个字符的密码

3.十个字符的密码

4.二十个字符的密码

5.对于包含无效特殊字符(如分号)的密码

6.对于没有数字的密码

7.对于没有小写字母的密码

8.对于没有大写字母的密码

9.对于没有有效特殊字符的密码

10.对于有效的密码

  • 一个尺寸以内,[6-20]

  • 至少一个小写和大写字符

  • 至少一个数字

  • 没有无效的特殊字符

TestIsValidPassword

class TestIsValidPassword(unittest.TestCase):
   def test_empty_password(self):
       self.assertFalse(is_valid_password())

def test_password_of_size_three(self):
       self.assertFalse(is_valid_password("pas"))

def test_password_of_size_ten(self):
       self.assertFalse(is_valid_password("Password12"))
       self.assertTrue(is_valid_password("Password1_"))

def test_password_of_size_twenty(self):
       self.assertFalse(is_valid_password("Password12Password_$"))

def test_password_with_invalid_special_character_semicolon(self):
       self.assertFalse(is_valid_password("Password1_;"))
       self.assertFalse(is_valid_password("Password1;"))

def test_password_with_no_digit(self):
       self.assertFalse(is_valid_password("Password_"))

def test_password_with_no_lowercase(self):
       self.assertFalse(is_valid_password("PASSWORD1_"))

def test_password_with_no_uppercase(self):
       self.assertFalse(is_valid_password("password1_"))

def test_password_without_valid_special_character(self):
       self.assertFalse(is_valid_password("Password1"))

def test_valid_password(self):
       self.assertTrue(is_valid_password("Password1_"))
       self.assertTrue(is_valid_password("PassWord34$"))

if __name__ == "__main__":
   unittest.main()

不是所有的测试都通过了。这些测试用例不应该通过&mdash;&mdash;我们期望它们不会通过。所以当我们期待False我们得到True。某处存在缺陷或错误。

这些测试没有通过:

  • test_password_of_size_ten : self.assertFalse(is_valid_password("Password12"))应该是False因为即使大小有效,它也没有特殊字符。

  • test_password_without_valid_special_character : self.assertFalse(is_valid_password("Password1"))应该是False因为没有有效的特殊字符。

这is_valid_password函数不检查是否存在有效的特殊字符。它检查无效字符,但不检查有效字符。这是由有缺陷的假设造成的,即只要密码不包含无效字符,它就包含有效字符(包括有效的特殊字符)。

重构is_valid_password

既然我们已经指出了我们的bug,我们应该做出改变并重新运行测试。

要进行的更改:

在&hellip;里get_invalid_chars,我们有set有效的特殊字符,valid_chars。让我们让它对所有函数都是全局的(例如,把它从get_invalid_chars函数并将其放在函数的顶部)。为了确保某处没有损坏,运行测试(我们预计有两种情况会失败)。请注意,即使我们移动valid_chars由于get_invalid_chars , get_invalid_chars应该还能正常工作。

这valid_chars是一个set,它可以用作中的一组get_invalid_chars . contains_character需要一段时间string sack作为论据。我们必须解析valid_chars如同string。让我们在下面创建一个函数get_invalid_chars返回一个string版本valid_chars 

def get_valid_chars():
   return "".join(valid_chars)

进行测试。

让我们检查中的有效字符is_valid_password通过在return True中的语句try封锁。

if not contains_character(new_password, get_valid_chars()):
   return False

进行测试。现在,所有的测试都通过了。万岁!!:clap:️:clap:️:clap:️

这更多的是重新排列代码is_valid_password在另一种环境中自然运行良好。我们将重新排列代码is_valid_password按此顺序分别为:size, lower case, upper case, digit, invalid special character and valid special character进行测试。

结论

这is_valid_password会在app.py类似于下面的代码片段:

from string import (ascii_lowercase, ascii_uppercase, digits, punctuation,
                   whitespace)
valid_chars = {'-', '_', '.', '!', '@', '#', '$', '^', '&', '(', ')'}

def contains_character(password: str = "", sack: str = "") -> bool:
   has_char = False

for char in password:
       if char in sack:
           has_char = True
           break

return has_char

def is_valid_size(password: str = "") -> bool:
   MIN_SIZE = 6
   MAX_SIZE = 20
   password_size = len(password)

return MIN_SIZE <= password_size <= MAX_SIZE

def get_invalid_chars():
   invalid_chars = set(punctuation + whitespace) - valid_chars
   return "".join(invalid_chars)

def get_valid_chars():
   return "".join(valid_chars)

def is_valid_password(password: str = "") -> bool:
   try:
       if not password:
           return False

new_password = password.strip()

if not is_valid_size(new_password):
           return False

if not contains_character(new_password, ascii_lowercase):
           return False

if not contains_character(new_password, ascii_uppercase):
           return False

if not contains_character(new_password, digits):
           return False

if contains_character(new_password, get_invalid_chars()):
           return False

if not contains_character(new_password, get_valid_chars()):
           return False

return True
   except:
       return False

单元测试将会在test.py类似于下面的代码片段:

import unittest
from app import (contains_character, is_valid_size, is_valid_password)

class TestContainsCharacter(unittest.TestCase):
   def test_empty_password_or_and_empty_sack(self):
       self.assertFalse(contains_character())

def test_char_i_in_str_python(self):
       self.assertFalse(contains_character("i", "python"))

def test_str_py_in_str_python(self):
       self.assertTrue(contains_character("py", "python"))

def test_str_python_in_str_python(self):
       self.assertTrue(contains_character("python", "python"))

class TestIsValidSize(unittest.TestCase):
   def test_empty_password(self):
       self.assertFalse(is_valid_size(""))

def test_4_char_password(self):
       self.assertFalse(is_valid_size("pass"))

def test_6_char_password(self):
       self.assertTrue(is_valid_size("passwd"))

def test_16_char_password(self):
       self.assertTrue(is_valid_size("ThisIs1Password!"))

def test_20_char_password(self):
       self.assertTrue(is_valid_size("ThisIs1Password!/+20"))

def test_21_char_password(self):
       self.assertFalse(is_valid_size("ThisIs1Password!/+20&"))

class TestIsValidPassword(unittest.TestCase):
   def test_empty_password(self):
       self.assertFalse(is_valid_password())

def test_password_of_size_three(self):
       self.assertFalse(is_valid_password("pas"))

def test_password_of_size_ten(self):
       self.assertFalse(is_valid_password("Password12"))
       self.assertTrue(is_valid_password("Password1_"))

def test_password_of_size_twenty(self):
       self.assertTrue(is_valid_password("Password12Password_$"))

def test_password_with_invalid_special_character_semicolon(self):
       self.assertFalse(is_valid_password("Password1_;"))
       self.assertFalse(is_valid_password("Password1;"))

def test_password_with_no_digit(self):
       self.assertFalse(is_valid_password("Password_"))

def test_password_with_no_lowercase(self):
       self.assertFalse(is_valid_password("PASSWORD1_"))

def test_password_with_no_uppercase(self):
       self.assertFalse(is_valid_password("password1_"))

def test_password_without_valid_special_character(self):
       self.assertFalse(is_valid_password("Password1"))

def test_valid_password(self):
       self.assertTrue(is_valid_password("Password1_"))
       self.assertTrue(is_valid_password("PassWord34$"))

if __name__ == "__main__":
   unittest.main()

来源:https://blog.csdn.net/weixin_52994140/article/details/123003338

标签:Python,密码,验证
0
投稿

猜你喜欢

  • Python无头爬虫下载文件的实现

    2023-11-30 03:24:00
  • 浅谈Python线程的同步互斥与死锁

    2022-06-26 17:38:37
  • Python中操作文件之write()方法的使用教程

    2023-12-29 06:06:13
  • Python随手笔记之标准类型内建函数

    2022-10-23 11:00:45
  • 了解WEB页面工具语言XML(四)应用分类

    2008-09-05 17:18:00
  • 能否推荐一个论坛用的数据库结构?

    2009-11-01 18:09:00
  • Java使用正则表达式验证用户名和密码的方法

    2023-06-13 18:05:56
  • 6个asp判断函数使用方法介绍

    2007-09-24 13:10:00
  • python解决12306登录验证码的实现

    2023-05-29 10:28:35
  • 使用javascript修复浏览器中12个常见而又头痛的问题

    2008-10-28 19:38:00
  • 404错误伪静态类封装class RewriteBase

    2009-06-29 16:19:00
  • 微信小程序简单的canvas裁剪图片功能详解

    2023-08-24 07:49:20
  • 每个ASP程序员必备的知识

    2008-09-21 21:34:00
  • 十分钟搞定pandas(入门教程)

    2023-08-09 01:00:15
  • Python实现微信中找回好友、群聊用户撤回的消息功能示例

    2022-02-04 02:51:02
  • 网页设计应急小技巧

    2011-10-05 18:52:57
  • pytorch 实现查看网络中的参数

    2023-10-28 22:08:37
  • 详解Python3序列赋值、序列解包

    2022-04-19 05:24:51
  • asp如何做一个随机密码产生器?

    2010-07-12 18:57:00
  • 关于Kotlin中SAM转换的那些事

    2022-02-09 15:14:38
  • asp之家 网络编程 m.aspxhome.com