python 密码验证

题目描述:

(1)模拟登陆界面,判别用户名和密码,给出合适的提示,如果超过三次,锁定输入。用代替密码;或者最新输入显示,前面的变成;安全性措施。

(2)同时添加如下图的加强验证(京东)。

(3)在触动滚动条时再出现空缺位置。

拓展:

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

增加数字验证码区别人机

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

滑块验证就是将滑块的移动和图片小块的移动相绑定,在滑块松开时触发相对应的检查函数,为了有一定的容错率,设定滑块的位置与设定的位置相差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)  # 点击取消滑动验证

运行结果






全部背景图片:

注册界面:


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容