python 密碼驗(yàn)證

題目描述:

(1)模擬登陸界面,判別用戶名和密碼,給出合適的提示,如果超過(guò)三次,鎖定輸入。用代替密碼;或者最新輸入顯示,前面的變成;安全性措施。

(2)同時(shí)添加如下圖的加強(qiáng)驗(yàn)證(京東)。

(3)在觸動(dòng)滾動(dòng)條時(shí)再出現(xiàn)空缺位置。

拓展:

增加注冊(cè)頁(yè)面,可供用戶注冊(cè)新用戶

增加數(shù)字驗(yàn)證碼區(qū)別人機(jī)

解題思路/算法分析/問(wèn)題及解決

滑塊驗(yàn)證就是將滑塊的移動(dòng)和圖片小塊的移動(dòng)相綁定,在滑塊松開(kāi)時(shí)觸發(fā)相對(duì)應(yīng)的檢查函數(shù),為了有一定的容錯(cuò)率,設(shè)定滑塊的位置與設(shè)定的位置相差3個(gè)像素以內(nèi)即算驗(yàn)證成功。

每次的位置隨機(jī)生成,同時(shí)隨即從14張事先準(zhǔn)備好的圖片中選取一張作為背景圖。

圖片小塊和背景圖片分別放在兩個(gè)不同的QLabel容器中。

每次刷新時(shí)將背景圖片的相應(yīng)位置摳出放于圖片小塊中,并將背景圖片的相應(yīng)部分置為白色以示區(qū)別。

拓展:

新增注冊(cè)頁(yè)部分就是點(diǎn)擊按鈕彈出注冊(cè)頁(yè)的對(duì)話框,可在里面輸入新用戶信息并保存到用戶信息字典中,隨后可用新注冊(cè)的用戶登錄。

數(shù)字驗(yàn)證碼由4位數(shù)字0-9和字母a-z及A-Z組成,隨機(jī)在可行字符集中選取4個(gè)字符組成四位驗(yàn)證碼,然后自動(dòng)生成驗(yàn)證碼以圖片的方式呈現(xiàn)給用戶。

實(shí)驗(yàn)代碼

登錄主界面:

登錄驗(yàn)證:

def check_login_func(self):

? ? ? ? if not self.validate_line.text():

? ? ? ? ? ? QMessageBox.warning(self, "警告", "還未輸入驗(yàn)證碼")

? ? ? ? ? ? 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", "密碼輸錯(cuò)次數(shù)已達(dá)三次!")

? ? ? ? ? ? ? ? ? ? self.close()

? ? ? ? ? ? self.user_line.clear()

? ? ? ? ? ? self.pwd_line.clear()

? ? ? ? ? ? self.validate_line.clear()

? ? ? ? else:

? ? ? ? ? ? QMessageBox.critical(self, "wrong", "驗(yàn)證碼輸入有誤!")

? ? ? ? ? ? self.refresh()

? ? ? ? ? ? self.validate_line.clear()

自動(dòng)生成驗(yàn)證碼圖片:

def get_chars():

? ? ? ? """生成給定長(zhǎng)度的字符串,返回列表格式"""

? ? ? ? return random.sample(chars, length)

? ? def create_lines():

? ? ? ? """繪制干擾線"""

? ? ? ? line_num = random.randint(*n_line)? # 干擾線條數(shù)

? ? ? ? for i in range(line_num):

? ? ? ? ? ? # 起始點(diǎn)

? ? ? ? ? ? begin = (random.randint(0, size[0]), random.randint(0, size[1]))

? ? ? ? ? ? # 結(jié)束點(diǎn)

? ? ? ? ? ? end = (random.randint(0, size[0]), random.randint(0, size[1]))

? ? ? ? ? ? draw.line([begin, end], fill=(0, 0, 0))

? ? def create_points():

? ? ? ? """繪制干擾點(diǎn)"""

? ? ? ? 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():

? ? ? ? """繪制驗(yàn)證碼字符"""

? ? ? ? c_chars = get_chars()

? ? ? ? strs = ' %s ' % ' '.join(c_chars)? # 每個(gè)字符前后以空格隔開(kāi)

? ? ? ? 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()

? ? # 圖形扭曲參數(shù)

? ? 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)? # 創(chuàng)建扭曲

? ? img = img.filter(ImageFilter.EDGE_ENHANCE_MORE)? # 濾鏡,邊界加強(qiáng)(閾值更大)

? ? mstream = io.BytesIO()

? ? img.save(mstream, img_type)

? ? if save_img:

? ? ? ? img.save("validate.jpg", img_type)

? ? return mstream, strs

注冊(cè)界面部分:

頁(yè)面初始化:

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)

注冊(cè)檢驗(yàn)部分:

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()

滑塊驗(yàn)證部分:

class Validate_page(QDialog):

? ? def __init__(self):

? ? ? ? super(Validate_page, self).__init__()

? ? ? ? self.resize(600, 500)

? ? ? ? self.setWindowTitle("拖動(dòng)滑塊驗(yàn)證")

? ? ? ? self.initUI()

? ? ? ? self.Widget_init()

? ? ? ? self.refresh()

? ? ? ? # self.show()

? ? def initUI(self):

? ? ? ? # 初始化相關(guān)控件位置

? ? ? ? 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):

? ? ? ? # 初始化相關(guān)組件的信號(hào)連接

? ? ? ? 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

? ? ? ? # 隨機(jī)生成驗(yàn)證區(qū)域

? ? ? ? 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? # 將被扣區(qū)域置為白色

? ? ? ? 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):? # 檢驗(yàn)滑動(dòng)驗(yàn)證是否成功

? ? ? ? # 獲取設(shè)定區(qū)域坐標(biāo)

? ? ? ? x = self.lb_sl.pos().x()

? ? ? ? y = self.lb_sl.pos().y()

? ? ? ? print(f"({x},{y})")

? ? ? ? if abs(x - self.answer_x) <= 3:? # 容錯(cuò)為3px

? ? ? ? ? ? QMessageBox.information(self, "恭喜", "驗(yàn)證成功")

? ? ? ? ? ? self.done(1)

? ? ? ? else:

? ? ? ? ? ? QMessageBox.critical(self, "錯(cuò)誤", "驗(yàn)證失敗")

? ? ? ? ? ? self.slider.setValue(0)

? ? ? ? ? ? self.refresh()

? ? def cancel(self):

? ? ? ? self.done(0)? # 點(diǎn)擊取消滑動(dòng)驗(yàn)證

運(yùn)行結(jié)果






全部背景圖片:

注冊(cè)界面:


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容