如何在 Python 中测试正则表达式密码?

Posted

技术标签:

【中文标题】如何在 Python 中测试正则表达式密码?【英文标题】:How to test a regex password in Python? 【发布时间】:2011-02-28 18:12:23 【问题描述】:

在 Python 中使用正则表达式,我如何验证用户的密码是:

至少 8 个字符 必须限于,但不具体要求: 大写字母:A-Z 小写字母:a-z 数字:0-9 任何特殊字符:@#$%^&+=

注意,所有字母/数字/特殊字符都是可选的。我只想验证密码长度是否至少为 8 个字符,并且仅限于字母/数字/特殊字符。如果他们愿意,用户可以选择更强/更弱的密码。 到目前为止,我所拥有的是:

import re
pattern = "^.*(?=.8,)(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).*$"
password = raw_input("Enter string to test: ")
result = re.findall(pattern, password)
if (result):
    print "Valid password"
else:
    print "Password not valid"

【问题讨论】:

我建议不要在这个测试中使用正则表达式。这样维护起来要容易得多。 其实,这个正则表达式一点也不复杂,而且很有意义。 Amber 的回答是正确的,但是虽然允许 aaaaaaaa 的密码验证器可能是“已验证”,但“如果他们愿意”允许这样的弱密码并不比接受 @ 的验证器好多少987654323@。值得注意的是,用户最喜欢的密​​码之一是password;如果您允许这样做,您不妨完全跳过密码。 @Amber,不使用正则表达式的重点不是因为正则表达式不好,而是因为维护正则表达式并不容易,而且密码要求是经常变化的东西。正如您的答案所示,他的示例对于正则表达式来说是“简单的”。但是一旦有人说这 4 个字符集中必须至少有 3 个:至少 1 个大写,至少 1 个小写,至少 1 个数字和至少 1 个特殊字符,复杂度就会上升。 @jmucchiello - 维护正则表达式只有在您采用必须在单个正则表达式中完成的方法时才复杂,无论它有多复杂。 “智能”方法是使用正则表达式(因为它们进行许多测试的有效方法),但不要试图将太多内容集中到同一个正则表达式中。例如,在您的示例中,那些“至少 1 个”测试可以在 additional 代码中完成,它们不必添加到同一个正则表达式中。 【参考方案1】:
import re
password = raw_input("Enter string to test: ")
if re.fullmatch(r'[A-Za-z0-9@#$%^&+=]8,', password):
    # match
else:
    # no match

8, 表示“至少 8 个”。 .fullmatch 函数要求整个字符串匹配整个正则表达式,而不仅仅是一部分。

【讨论】:

好吧,我不得不承认这是可读的,如果它不打算改变,那么它是一个很好的解决方案。像“如果业务逻辑发生变化,正则表达式并不总是合适”这样的评论可能会有所帮助,但话又说回来 - 维护者并不愚蠢 - 你必须做出这样的假设,对吧? @Hamish- 我不知道。即使维护者是我自己。将来有人会被分配对该代码的更改,他会考虑更新正则表达式作为在一段时间内进行的“唯一”方式,直到他想出一些有效的 Rube Goldberg 正则表达式,或者他注意到他正在使用 3几天来进行快速更改并最终放弃正则表达式结构。 好吧,我最近加入了一家公司并修复了几个月的错误。我有很多WTF? 时刻,这让我向其他人提问并学习东西。通常的解释是:我们在 4/6/8/10 年前写了这篇文章,这就是当时的做法。我觉得既然我通过了通过修复错误来学习混乱系统的测试,其他人也应该如此。如果初级程序员过得很轻松,那么[s]他要么太聪明,不适合团队,要么没有学习。如果你总是使用卫生代码,那么你的“免疫系统”就会受到攻击和/或开始攻击友好的代码。 Amber,您是绝对正确的,而且似乎许多 cmets 来自不了解您可以使用正则表达式做多少事情的人。为他们推荐这本书:Mastering Regular Expressions这将使他们成为更好的程序员。 这对我来说不像预期的那样工作。密码即使不包含符号也会作为匹配项出现。【参考方案2】:

我同意哈米什的观点。不要为此使用正则表达式。对每个测试使用离散函数,然后按顺序调用它们。明年,当您想在密码中要求至少 2 个大写字母和 2 个小写字母时,您将不会对尝试修改该正则表达式感到满意。

另一个原因是允许用户配置。假设你把你的程序卖给想要 12 个字符密码的人。修改单个函数来处理系统参数比修改正则表达式更容易。

// pseudo-code
Bool PwdCheckLength(String pwd)

    Int minLen = getSystemParameter("MinPwdLen");
    return pwd.len() < minlen;

【讨论】:

我不确定的一件事是:是否应该只警告用户一种类型的错误(无效密码),还是所有不同类型的错误?我想这取决于业务逻辑。 如果他以后需要更改密码有效性要求,他是否使用正则表达式今天都没有关系。它只是一个返回truefalse 的函数(至少应该是),它是否使用正则表达式都没有关系。 取决于观众。如果用户通常是预先验证的(例如在 Intranet 应用程序上),您希望握住他们的手并降低支持成本。在野外,所有这些都是告诉你的潜在攻击者如何减少他的字典的大小。我认为这就是为什么您会在某些网站上看到这些算法显示密码强度的原因。他们没有告诉你到底想要什么,但仍然以某种方式执行规则。给用户的注释可以只是说“必须是 60% 或更好”。 (当然,当这些东西只是 javascript 并不能阻止攻击者阅读代码时。) @Deniz - 维护一堆小函数比维护单个复杂的正则表达式要容易得多。如果您想对此进行辩论,那么您生活在与我不同的编程世界中。 这个世界上有10种人:会用Perl的和不会用的;)【参考方案3】:

嗯,这是我的非正则表达式解决方案(仍然需要一些工作):

#TODO: the initialization below is incomplete
hardCodedSetOfAllowedCharacters = set(c for c in '0123456789a...zA...Z~!@#$%^&*()_+')
def getPassword():
    password = raw_input("Enter string to test: ").strip()
    if (len(password) < 8):
        raise AppropriateError("password is too short")
    if any(passChar not in hardCodedSetOfAllowedCharacters for passChar in password):
        raise AppropriateError("password contains illegal characters")
    return password

【讨论】:

您可以使用string 模块使hardCodedSetOfAllowedCharacters 的创建更容易/更具可读性:set(string.letters + string.digits + '@#$%^&amp;+=')。此外,因为 set 接受任何可迭代(并且字符串是可迭代的),所以您不需要生成器表达式。【参考方案4】:
import re
password=raw_input("Please give me a password: ")
if len(re.findall("[A-Za-z0-9@#$%^&+=]",password))==len(password):
    print("Great password")
else:
    print("Incorrect password")

如果您想在 python 3.0 及更高版本中运行它,请使用输入更改 raw_input。

【讨论】:

然后你可以将len的限制设置为大于8。 最好编辑你的答案而不是评论它。【参考方案5】:
import re 

password = input("Enter Password")
True if (re.fullmatch(r'^[A-Za-z0-9@#$%^&+=]8,$', password)) else False

如果您想制作所需的第二位,您可以执行以下操作:-

True if (re.fullmatch(r'^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.[@#$%^&+=])[A-Za-z0-9@#$%^&+=]8,$', password)) else False

注意:python 中的 [0-9] 是 \d 的子集,因此您可能要坚持使用 [0-9] 阅读以下帖子https://***.com/a/6479605/4170558

【讨论】:

【参考方案6】:

如果您希望程序持续运行直到输入正确的密码,请执行以下操作。

import re

while True:
    print('Input a strong password.')
    password = input()
    if re.match(r'[A-Za-z0-9@#$%^&+=]8,', password):
        print('Very nice password. Much secure')
        break
    else:
        print('Not a valid password')

【讨论】:

【参考方案7】:

这个正则表达式验证密码:

大写字母:A-Z -小写字母:a-z 数字:0-9

任何一个 特殊字符:!@£$%^&*()_+=?:~[]]+

re.compile(r'^.*(?=.8,10)(?=.*[a-zA-Z])(?=.*?[A-Z])(?=.*\d)[a-zA-Z0-9!@£$%^&*()_+=?:~\[\]]+$')

【讨论】:

以上是关于如何在 Python 中测试正则表达式密码?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Python 中传递包含正则表达式的参数?

正则表达式-JavaScript 密码测试

python中用正则表达式检查密码是否安全

用于测试密码强度的正则表达式

python 使用正则表达式判断密码强弱

day22.正则表达式Python教程