鱼C论坛

 找回密码
 立即注册
查看: 2448|回复: 4

[学习笔记] 字符串之密码安全检测

[复制链接]
发表于 2020-2-12 15:50:38 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 233倔强不秃 于 2020-2-12 16:06 编辑

一、引言:
      本题来自python课后习题014的动动手动动手,题目如下:
  
0. 请写一个密码安全性检查的代码代码:check.py
  
# 密码安全性检查代码
#
# 低级密码要求:
#   1. 密码由单纯的数字或字母组成
#   2. 密码长度小于等于8位
#
# 中级密码要求
#   1. 密码必须由数字、字母或特殊字符(仅限:~!@#$%^&*()_=-/,.?<>;:[]{}|\)任意两种组合
#   2. 密码长度不能低于8位
#
# 高级密码要求:
#   1. 密码必须由数字、字母及特殊字符(仅限:~!@#$%^&*()_=-/,.?<>;:[]{}|\)三种组合
#   2. 密码只能由字母开头
#   3. 密码长度不能低于16位


二、分析:

       1.检测为低级时:用字符串的BIF,isdigit()和isalpha()  检测是否全为数字或者字母。
       2.将数字、字母、特殊符号分别存为三个字符串或者列表,用for循环和in判断其组成
       3.程序主体还是用if...elif...else

三、源代码:
code = input('请输入进行安全性检查的密码:')
low = code.isalpha() or code.isdigit() #是否全是数字或字母
size = len(code)    #长度
num = '123456790'
s = '~#$%^&*()_=-/,.?<>;:[]{}|\!@'
al = [ chr(i) for i in range(97,123)]#列表推导式

try:
    #判断密码中是否有数字,若有则返回true
    num_flag = 0
    for i in code:
        if i in num:
            num_flag = 1
            break
            
    #判断密码中是否有字母,若有则返回true
    code = code.lower()#全部转化为小写
    a_flag = 0
    for i in code:
        if i in al:
            a_flag = 1
            break

    #判断第一个字符是否是字母
    f_flag = code[0] in al

    #判断密码中是否有符号,若有则返回true
    s_flag = 0
    for i in code:
        if i in s:
            s_flag = 1
            break

    #判断是否有其中两种
    mid = (num_flag and a_flag)or(num_flag and s_flag)or(a_flag and s_flag)

    #判断是否三种都有
    high = num_flag and a_flag and s_flag

    def talk(): #打印提示
        print('请按以下方法提升您的密码安全级别:')
        print('\t1.密码必须由数字、字母及特殊字符三种组合')
        print('\t2.密码只能由字母开头')
        print('\t3.密码长度不能低于16位')

    if size<=8 or low:                 #低
        print('您的密码安全级别评定为:低')
        talk()

    elif (16>size>=8) or (mid and not high) :
        print('您的密码安全级别评定为:中')
        talk()

    elif(size>=16) and high and f_flag:
        print('您的密码安全级别评定为:高')
        print('请继续保持!')

    else:
        print('请检查您输入的密码是否符合要求!')
        print('原因如下:')
        print('1.输入为空')
        print('2.存在非法字符')
        
except:
    print('检测到输入的密码为空!')
    


代码解释:
1.获取26个字母组成的list时,用了chr()函数,将ASCII码转换为对应字符。
2.当输入为空白时,f_flag = code[0] in al这个地方将会出错,因为code[0]不存在。所以用了异常处理try-except语句,虽然except后面什么也没有这种写法很不推荐,但是在这个程序中应该只会报这一种错,这样写应该没有问题。
3.还写了一个打印提示的函数talk。
4.用了lower()函数将字符串中的字母变为小写。
5.判断了字符串中是否包含有数字,字母或者特殊字符之后,将if后面的条件写在了外面,if里面直接写结果就行。

四、不足之处:

先看一下标准答案:
symbols = r'''`!@#$%^&*()_+-=/*{}[]\|'";:/?,.<>'''
chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
nums = '0123456789'

passwd = input('请输入需要检查的密码组合:')

# 判断长度
length = len(passwd)

while (passwd.isspace() or length == 0) :
    passwd = input("您输入的密码为空(或空格),请重新输入:")
    length = len(passwd)

if length <= 8:
    flag_len = 1
elif 8 < length < 16:
    flag_len = 2
else:
    flag_len = 3

flag_con = 0

# 判断是否包含特殊字符
for each in passwd:
    if each in symbols:
        flag_con += 1
        break
    
# 判断是否包含字母
for each in passwd:
    if each in chars:
        flag_con += 1
        break

# 判断是否包含数字
for each in passwd:
    if each in nums:
        flag_con += 1
        break    

# 打印结果
while 1 :
    print("您的密码安全级别评定为:", end='')
    if flag_len == 1 or flag_con == 1 :
        print("低")
    elif flag_len == 3 and flag_con == 3 and (passwd[0] in chars):
        print("高")
        print("请继续保持")
        break
    else:
        print("中")

    print("请按以下方式提升您的密码安全级别:\n\
    \t1. 密码必须由数字、字母及特殊字符三种组合\n\
    \t2. 密码只能由字母开头\n\
    \t3. 密码长度不能低于16位")
    break
   
不得不说,姜还是老的辣。小甲鱼的写法中间有很多值得借鉴和学习的地方:
1. 直接用isspace()函数判断输入是否为空,就不用费事了。
2.将等级判断问题简化为:长度和复杂度,而更巧妙的是,我们都知道标签法设置flag,看到flag的值不是1或0还是第一次。小甲鱼将flag的值直接对应了等级,分别为1,2,3
3.设置等级判断的顺序为低,高,中,这样中等级就省去了判断,而且还避免了中等级和高等级判断时容易犯的错。
3.while1的巧妙用法:将打印提示写在最后,如果不是高等级,就要执行打印提示,高等级直接break。这样设置很巧妙,减少了代码量,而我还设了函数去打印。。。

五、总结:

      总结好的写法和好的思路,多实践将优点吸收。

评分

参与人数 1荣誉 +3 鱼币 +3 贡献 +2 收起 理由
zltzlt + 3 + 3 + 2 鱼C有你更精彩^_^

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-3-8 16:29:06 | 显示全部楼层
symbols = r'''`!@#$%^&*()_+-=/*{}[]\|'";:/?,.<>'''
chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
nums = '0123456789'
password=input('请输入你的密码:')
l=len(password)
while (l==0 or password.isspace()):
    password=input('输入有误,请重新输入')
if l<=8:
    safe_l=1
elif 8<=l<16:
    safe_l=2
else:
    safe_l=3
safe_con=0
for each in password:
    if each in symbols:
        safe_con+=1
    for each in password:
        if each in chars:
            safe_con+=1
        for each in password:
            if each in nums:
                safe_con+=1
                break
while 1:
    print('您的密码安全级别评级为:',end='')
    if safe_l==1 or safe_con==0:
        print('低')
        
    elif safe_l==3 and safe_con==3 and (password[0] in chars):
        print('高,请继续保持')
        break
    else:
        print('中')
    print("请按以下方式提升您的密码安全级别:\n\
    \t1. 密码必须由数字、字母及特殊字符三种组合\n\
    \t2. 密码只能由字母开头\n\
    \t3. 密码长度不能低于16位")
    break
麻烦大神看一下等级高为什么判断不出来?哪里出错了?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-3-12 00:26:25 | 显示全部楼层
code = input('请输入进行安全性检查的密码:')
low = code.isalpha() or code.isdigit() #是否全是数字或字母
size = len(code)    #长度
num = '123456790'
s = '~#$%^&*()_=-/,.?<>;:[]{}|\!@'
al = [ chr(i) for i in range(97,123)]#列表推导式


try:
    #判断密码中是否有数字,若有则返回true
    num_flag = 0
    for i in code:
        if i in num:
            num_flag = 1
            break
            
    #判断密码中是否有字母,若有则返回true
    code = code.lower()#全部转化为小写
    a_flag = 0
    for i in code:
        if i in al:
            a_flag = 1
            break

    #判断第一个字符是否是字母
    f_flag = code[0] in al

    #判断密码中是否有符号,若有则返回true
    s_flag = 0
    for i in code:
        if i in s:
            s_flag = 1
            break

    #判断是否有其中两种
    mid = (num_flag and a_flag)or(num_flag and s_flag)or(a_flag and s_flag)

    #判断是否三种都有
    high = num_flag and a_flag and s_flag

    def talk(): #打印提示
        print('请按以下方法提升您的密码安全级别:')
        print('\t1.密码必须由数字、字母及特殊字符三种组合')
        print('\t2.密码只能由字母开头')
        print('\t3.密码长度不能低于16位')

    if size<=8 or low:                 #低
        print('您的密码安全级别评定为:低')
        talk()

        
    elif(size>=16) and high and f_flag:
        print('您的密码安全级别评定为:高')
        print('请继续保持!')


    else:
        print('您的密码安全级别评定为:中')
        talk()

    
        
except:
    print('检测到输入的密码为空!')
    
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-3-12 00:28:00 | 显示全部楼层
上面的代码有逻辑漏洞,如果其他条件都满足高等级,但是第一个字符不是字母,本应该是中等级,但是却判断不出来,下面是修改后的代码。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-3-12 00:35:21 | 显示全部楼层
毛小毛 发表于 2020-3-8 16:29
symbols = r'''`!@#$%^&*()_+-=/*{}[]\|'";:/?,.'''
chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNO ...

for each in password:
    if each in symbols:
        safe_con+=1
    for each in password:
        if each in chars:
            safe_con+=1
        for each in password:
            if each in nums:
                safe_con+=1
                break
你这个地方的缩进有问题,而且三个for循环只有一个有break出口。那就意味着,你的safe_con的值不是代表密码中包含字符的种类,而是变成了统计每个字符串中各种字符的个数,在每个for循环里加上break就好了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-17 23:25

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表