python 密码验证(滑块验证)

作者:Andy-wen 时间:2021-01-24 02:32:18 

题目描述:

(1)模拟登陆界面,判别用户名和密码,给出合适的提示,如果超过三次,锁定输入。用代替密码;或者最新输入显示,前面的变成;安全性措施。
(2)同时添加如下图的加强验证(京东)。
(3)在触动滚动条时再出现空缺位置。

python 密码验证(滑块验证)

拓展:

  • 增加注册页面,可供用户注册新用户

  • 增加数字验证码区别人机

解题思路/算法分析/问题及解决

滑块验证就是将滑块的移动和图片小块的移动相绑定,在滑块松开时触发相对应的检查函数,为了有一定的容错率,设定滑块的位置与设定的位置相差3个像素以内即算验证成功。

  • 每次的位置随机生成,同时随即从14张事先准备好的图片中选取一张作为背景图。

  • 图片小块和背景图片分别放在两个不同的QLabel容器中。

  • 每次刷新时将背景图片的相应位置抠出放于图片小块中,并将背景图片的相应部分置为白色以示区别。

  • 拓展:

  • 新增注册页部分就是点击按钮弹出注册页的对话框,可在里面输入新用户信息并保存到用户信息字典中,随后可用新注册的用户登录。

  • 数字验证码由4位数字0-9和字母a-z及A-Z组成,随机在可行字符集中选取4个字符组成四位验证码,然后自动生成验证码以图片的方式呈现给用户。

实验代码

登录主界面:
登录验证:

def check_login_func(self):
       if not self.validate_line.text():
           QMessageBox.warning(self, "警告", "还未输入验证码")
           return
       validate_slide = Validate_page()
       r = validate_slide.exec_()
       if not r:
           return
       if self.validate.upper() == self.validate_line.text().upper():
           if USER_PWD.get(self.user_line.text()) == self.pwd_line.text():
               QMessageBox.information(self, 'Information', 'Log in Successfully!')
               self.nums = 0
               self.refresh()
               # self.close()
               # self.STU.exec()
           else:
               QMessageBox.critical(self, 'Wrong', 'Wrong Username or Password!')
               self.nums = self.nums + 1
               if self.nums == 3:
                   QMessageBox.critical(self, "wrong", "密码输错次数已达三次!")
                   self.close()

self.user_line.clear()
           self.pwd_line.clear()
           self.validate_line.clear()
       else:
           QMessageBox.critical(self, "wrong", "验证码输入有误!")
           self.refresh()
           self.validate_line.clear()

自动生成验证码图片:

def get_chars():
       """生成给定长度的字符串,返回列表格式"""

return random.sample(chars, length)

def create_lines():
       """绘制干扰线"""

line_num = random.randint(*n_line)  # 干扰线条数

for i in range(line_num):
           # 起始点
           begin = (random.randint(0, size[0]), random.randint(0, size[1]))
           # 结束点
           end = (random.randint(0, size[0]), random.randint(0, size[1]))
           draw.line([begin, end], fill=(0, 0, 0))

def create_points():
       """绘制干扰点"""

chance = min(100, max(0, int(point_chance)))  # 大小限制在[0, 100]

for w in range(width):
           for h in range(height):
               tmp = random.randint(0, 100)
               if tmp > 100 - chance:
                   draw.point((w, h), fill=(0, 0, 0))

def create_strs():
       """绘制验证码字符"""

c_chars = get_chars()
       strs = ' %s ' % ' '.join(c_chars)  # 每个字符前后以空格隔开

font = ImageFont.truetype(font_type, font_size)
       font_width, font_height = font.getsize(strs)

draw.text(((width - font_width) / 3, (height - font_height) / 3),
                 strs, font=font, fill=fg_color)

return ''.join(c_chars)

if draw_lines:
       create_lines()
   if draw_points:
       create_points()
   strs = create_strs()

# 图形扭曲参数
   params = [1 - float(random.randint(1, 2)) / 100,
             0,
             0,
             0,
             1 - float(random.randint(1, 10)) / 100,
             float(random.randint(1, 2)) / 500,
             0.001,
             float(random.randint(1, 2)) / 500
             ]
   img = img.transform(size, Image.PERSPECTIVE, params)  # 创建扭曲

img = img.filter(ImageFilter.EDGE_ENHANCE_MORE)  # 滤镜,边界加强(阈值更大)

mstream = io.BytesIO()
   img.save(mstream, img_type)

if save_img:
       img.save("validate.jpg", img_type)

return mstream, strs

注册界面部分:
页面初始化:

def __init__(self):
       super(SigninPage, self).__init__()
       self.signin_user_label = QLabel('Username:', self)
       self.signin_pwd_label = QLabel('Password:', self)
       self.signin_pwd2_label = QLabel('Password:', self)
       self.signin_user_line = QLineEdit(self)
       self.signin_pwd_line = QLineEdit(self)
       self.signin_pwd2_line = QLineEdit(self)
       self.signin_button = QPushButton('Sign in', self)

self.user_h_layout = QHBoxLayout()
       self.pwd_h_layout = QHBoxLayout()
       self.pwd2_h_layout = QHBoxLayout()
       self.all_v_layout = QVBoxLayout()

self.lineedit_init()
       self.pushbutton_init()
       self.layout_init()

def layout_init(self):
       self.user_h_layout.addWidget(self.signin_user_label)
       self.user_h_layout.addWidget(self.signin_user_line)
       self.pwd_h_layout.addWidget(self.signin_pwd_label)
       self.pwd_h_layout.addWidget(self.signin_pwd_line)
       self.pwd2_h_layout.addWidget(self.signin_pwd2_label)
       self.pwd2_h_layout.addWidget(self.signin_pwd2_line)

self.all_v_layout.addLayout(self.user_h_layout)
       self.all_v_layout.addLayout(self.pwd_h_layout)
       self.all_v_layout.addLayout(self.pwd2_h_layout)
       self.all_v_layout.addWidget(self.signin_button)

self.setLayout(self.all_v_layout)

def lineedit_init(self):
       self.signin_user_line.setPlaceholderText("username")
       self.signin_pwd_line.setPlaceholderText("password")
       self.signin_pwd2_line.setPlaceholderText("password again")

self.signin_pwd_line.setEchoMode(QLineEdit.Password)
       self.signin_pwd2_line.setEchoMode(QLineEdit.Password)

self.signin_user_line.textChanged.connect(self.check_input_func)
       self.signin_pwd_line.textChanged.connect(self.check_input_func)
       self.signin_pwd2_line.textChanged.connect(self.check_input_func)

注册检验部分:

def check_signin_func(self):
       if self.signin_pwd_line.text() != self.signin_pwd2_line.text():
           QMessageBox.critical(self, 'Wrong', 'Two Passwords Typed Are Not Same!')
       elif self.signin_user_line.text() not in USER_PWD:
           USER_PWD[self.signin_user_line.text()] = self.signin_pwd_line.text()
           QMessageBox.information(self, 'Information', 'Register Successfully')
           self.close()
       else:
           QMessageBox.critical(self, 'Wrong', 'This Username Has Been Registered!')

self.signin_user_line.clear()
       self.signin_pwd_line.clear()
       self.signin_pwd2_line.clear()

滑块验证部分:

class Validate_page(QDialog):
   def __init__(self):
       super(Validate_page, self).__init__()
       self.resize(600, 500)
       self.setWindowTitle("拖动滑块验证")
       self.initUI()
       self.Widget_init()
       self.refresh()
       # self.show()

def initUI(self):
       # 初始化相关控件位置
       self.lb_bg = QLabel(self)
       self.lb_sl = QLabel(self)

self.lb_bg.setStyleSheet("border: 2px solid red")
       # self.lb_sl.setStyleSheet("border: 2px solid blue")
       self.lb_bg.setGeometry(100, 100, 400, 200)

self.lb_wz = QLabel(self)
       # self.lb_wz.setStyleSheet("border: 2px solid green")

self.refresh()

self.button = QPushButton("取消", self)
       self.button.setGeometry(400, 430, 100, 50)

self.slider = QSlider(Qt.Horizontal, self)
       self.slider.setGeometry(100, 350, 400, 50)

def Widget_init(self):
       # 初始化相关组件的信号连接
       self.slider.setMinimum(0)
       self.slider.setMaximum(360)
       self.slider.valueChanged.connect(self.slide)
       self.slider.sliderReleased.connect(self.check)
       self.button.clicked.connect(self.cancel)

def slide(self, value):
       self.lb_sl.move(100 + value, self.answer_y)  # 将滑块与图片小块绑定
       # print(value)

def refresh(self):
       import random
       # 随机生成验证区域
       self.answer_x = random.randint(100, 460)
       self.answer_y = random.randint(100, 260)
       pic = random.randint(0, 14)

self.lb_sl.setGeometry(100, self.answer_y, 40, 40)
       self.lb_wz.setGeometry(self.answer_x, self.answer_y, 40, 40)
       img = cv2.imread(f"pic/{pic}.jpeg")  # 读取背景图片
       img = cv2.resize(img, (400, 200))
       x = self.answer_x - 100
       y = self.answer_y - 100
       img1 = copy.copy(img[y:y + 40, x:x + 40])  # 扣40*40的图片小块
       img[y:y + 40, x:x + 40] = 255  # 将被扣区域置为白色
       img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
       img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2RGB)

qt_img = QImage(img.data, 400, 200, QImage.Format_RGB888)
       qt_img1 = QImage(img1.data, 40, 40, QImage.Format_RGB888)
       self.lb_bg.setPixmap(QPixmap.fromImage(qt_img))
       self.lb_sl.setPixmap(QPixmap.fromImage(qt_img1))

def check(self):  # 检验滑动验证是否成功
       # 获取设定区域坐标
       x = self.lb_sl.pos().x()
       y = self.lb_sl.pos().y()
       print(f"({x},{y})")
       if abs(x - self.answer_x) <= 3:  # 容错为3px
           QMessageBox.information(self, "恭喜", "验证成功")
           self.done(1)
       else:
           QMessageBox.critical(self, "错误", "验证失败")
           self.slider.setValue(0)
           self.refresh()

def cancel(self):
       self.done(0)  # 点击取消滑动验证

运行结果

python 密码验证(滑块验证)

python 密码验证(滑块验证)

python 密码验证(滑块验证)

python 密码验证(滑块验证)

python 密码验证(滑块验证)

全部背景图片:

python 密码验证(滑块验证)

注册界面:

python 密码验证(滑块验证)

完整代码

来源:https://blog.csdn.net/weixin_45816954/article/details/123172595

标签:python,密码验证,滑块验证
0
投稿

猜你喜欢

  • 如何捕获人家站点的页面?

    2009-11-11 19:19:00
  • 三条asp语句搞定路径

    2007-10-22 13:30:00
  • IOS苹果AppStore内购付款的服务器端php验证方法(使用thinkphp)

    2023-06-14 13:05:56
  • 为什么python比较流行

    2023-06-26 02:24:22
  • 一些SQL查询语法参考

    2007-10-14 11:56:00
  • php 字符串中是否包含指定字符串的多种方法

    2023-06-11 20:21:38
  • Python三元运算与lambda表达式实例解析

    2023-06-14 16:34:09
  • Idea开发工具之SpringBoot整合JSP的过程

    2023-06-14 19:50:23
  • 注册和填表中常见的中英文对照

    2008-07-26 12:12:00
  • asp函数解决SQL注入漏洞

    2008-10-12 19:53:00
  • PHP实现无限极分类的两种方式示例【递归和引用方式】

    2023-11-15 18:26:33
  • SQLServer 2005中如何列所有存储过程

    2008-11-24 17:39:00
  • 对用户进行电话访谈的一点感想

    2009-12-28 13:05:00
  • 装载iframe 子页面,自适应高度

    2008-11-20 12:53:00
  • 立足于传统行业设计

    2008-07-26 12:36:00
  • 用ASP建立一个简单的聊天室

    2007-09-21 12:43:00
  • webpack学习教程之publicPath路径问题详解

    2023-07-16 06:09:52
  • 新版php study根目录下文件夹无法显示的图文解决方法

    2023-11-15 00:44:29
  • 2010怎么就宅了——我们是设计星球的阿凡达

    2010-03-09 13:26:00
  • Oracle数据库SQL语句性能调整的基本原则

    2009-03-25 16:55:00
  • asp之家 网络编程 m.aspxhome.com