이 내용은 이전 글과 연관되어 있습니다.
간단한 로그인 알고리즘 중 일정 횟수 비밀번호 에러가 발생하면 해당 계정의 로그인을 일시적으로(필자는 1분으로 설정하였음) 차단하는 기능을 구현해보겠습니다.
우선 크게 필요한 것은
첫 번째로 비밀번호 에러가 발생한 시간,
두 번째는 비밀번호 에러 횟수입니다.
현재 시간과 에러 발생 시간을 비교하여 로그인 성공 유무를 선택하는 알고리즘입니다.
자세한 것은 코드에 주석 처리 해놓았습니다.
#!/usr/bin/env python3
#
# Authors:
# 5jx2oh@gmail.com
import sys
import time
from datetime import datetime
from PySide6.QtCore import QSettings
from PySide6.QtCore import QCoreApplication, QMetaObject
from PySide6.QtWidgets import QFrame, QGridLayout, QLabel, \
QLineEdit, QPushButton, QSizePolicy, QWidget
from PySide6.QtWidgets import QDialog, QMessageBox
from PySide6.QtCore import Qt
# Ui
class Ui_Dialog(object):
def setupUi(self, Dialog):
if not Dialog.objectName():
Dialog.setObjectName(u"Dialog")
Dialog.resize(290, 200)
self.gridLayout = QGridLayout(Dialog)
self.gridLayout.setObjectName(u"gridLayout")
self.gridWidget = QWidget(Dialog)
self.gridWidget.setObjectName(u"gridWidget")
self.gridLayout_2 = QGridLayout(self.gridWidget)
self.gridLayout_2.setObjectName(u"gridLayout_2")
self.id_lineEdit = QLineEdit(self.gridWidget)
self.id_lineEdit.setObjectName(u"id_lineEdit")
self.id_lineEdit.setStyleSheet(u"background-color: #ffffff;")
self.gridLayout_2.addWidget(self.id_lineEdit, 2, 0, 1, 1)
self.alert_label = QLabel(self.gridWidget)
self.alert_label.setObjectName(u"alert_label")
self.alert_label.setEnabled(True)
sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.alert_label.sizePolicy().hasHeightForWidth())
self.alert_label.setSizePolicy(sizePolicy)
self.alert_label.setStyleSheet(u"color:#ff0000;")
self.alert_label.setFrameShadow(QFrame.Plain)
self.alert_label.setTextFormat(Qt.AutoText)
self.alert_label.setAlignment(Qt.AlignCenter)
self.gridLayout_2.addWidget(self.alert_label, 5, 0, 1, 1)
self.pw_lineEdit = QLineEdit(self.gridWidget)
self.pw_lineEdit.setObjectName(u"pw_lineEdit")
self.pw_lineEdit.setStyleSheet(u"background-color: #ffffff;")
self.pw_lineEdit.setEchoMode(QLineEdit.Password)
self.gridLayout_2.addWidget(self.pw_lineEdit, 3, 0, 1, 1)
self.gridLayout.addWidget(self.gridWidget, 0, 0, 1, 1)
self.login_button = QPushButton(Dialog)
self.login_button.setObjectName(u"login_button")
self.gridLayout.addWidget(self.login_button, 1, 0, 1, 1)
self.retranslateUi(Dialog)
QMetaObject.connectSlotsByName(Dialog)
# setupUi
def retranslateUi(self, Dialog):
Dialog.setWindowTitle(QCoreApplication.translate("Dialog", u"Login", None))
self.id_lineEdit.setPlaceholderText(QCoreApplication.translate("Dialog", u"ID", None))
self.alert_label.setText("")
self.pw_lineEdit.setPlaceholderText(QCoreApplication.translate("Dialog", u"Password", None))
self.login_button.setText(QCoreApplication.translate("Dialog", u"Login", None))
# retranslateUi
# Setting value
class MySetting:
settings = QSettings('Setting', 'hi~')
defaults = {
'login_id': 'admin',
'login_pw': 'admin',
'error_time': ''
}
@classmethod
def set(cls, key, value):
cls.settings.setValue(key, value)
@classmethod
def get(cls, key):
return cls.settings.value(
key,
cls.defaults[key],
type(cls.defaults[key])
)
@classmethod
def restore_defaults(cls):
for key, value in cls.defaults.items():
cls.set(key, value)
# Main Code
class LoginWindow(QDialog, Ui_Dialog):
def __init__(self):
super(LoginWindow, self).__init__()
self.setupUi(self)
self.setWindowFlag(Qt.WindowContextHelpButtonHint, False)
self.login_button.clicked.connect(self.login_click)
self.login_button.setShortcut('Return')
self.id = MySetting.get('login_id') # QSettings ID
self.pw = MySetting.get('login_pw') # QSettings 비밀번호
self.flag = 0 # 비밀번호 에러 카운트 값
def login_click(self):
input_id = self.id_lineEdit.text()
input_pw = self.pw_lineEdit.text()
if input_id == self.id and input_pw == self.pw: # Setting값의 ID와 PW값이 동일할 때
if MySetting.get('error_time') != '': # error_time 값이 Null이 아니라면, 즉 에러가 발생하였음을 의미
now = datetime.now() # 현재 시간
agga = datetime.strptime(MySetting.get('error_time'), '%Y-%m-%d %H:%M:%S')
# 에러 발생 시간을 현재 시간 Type으로 변경하여 비교할 준비
# 아까 에러가 발생한 시간이라는 뜻으로 agga ㅎ
diff = now - agga # 현재 시간 - 에러 발생 시간
if diff.seconds >= 60: # 현재 시간과 에러가 발생한 시간의 차이가 60초 이상이면 아래 조건문 실행
# 즉, 비밀번호 에러가 발생한지 1분이 지났으므로 로그인이 되어야 함
MySetting.set('error_time', '') # 에러 발생 시간 값을 초기화 = 에러가 발생한 적 없음
print('로그인 성공')
self.close()
else: # 에러가 발생한 지 아직 1분이 지나지 않았을 때
QMessageBox.warning(None, '계정 일시 차단', '해당 계정은 일시적으로 차단되었습니다.')
self.close()
sys.exit()
elif MySetting.get('error_time') == '': # 에러가 발생한 적 없을 때
print('로그인 성공')
self.close()
elif input_id != self.id: # 입력한 ID가 없을 때
self.alert_label.setText('없는 아이디 입니다.')
else: # 위 조건문들에 해당되지 않을 때, 즉 ID는 맞지만 비밀번호가 틀릴 때
if input_id == self.id:
self.flag += 1 # 비밀번호 에러 횟수 증가
self.alert_label.setText(f'비밀번호가 올바르지 않습니다. ({self.flag} / 5)')
if self.flag >= 5: # 비밀번호 에러가 5회 이상일 때
error_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) # 에러 발생 시간
QMessageBox.warning(None, '비밀번호 5회 오류로 인한 계정 차단', '잠시 후에 다시 로그인을 시도해 주세요.')
print(f'로그인 차단 시작 [{error_time}]')
MySetting.set('error_time', error_time) # 에러 발생 시간을 QSettings 값에 저장
self.close()
sys.exit()
def keyPressEvent(self, event):
if event.key() == Qt.Key_Escape:
sys.exit()
if __name__ == '__main__':
from PySide6.QtWidgets import QApplication
app = QApplication(sys.argv)
window = LoginWindow()
window.show()
sys.exit(app.exec())
기본 화면 |
없는 아이디 |
비밀번호 에러 |
5회 오류시 계정 차단 |
아직 1분이 지나지 않았을 때 계정 차단 안내 |
반응형
'Development > GUI' 카테고리의 다른 글
Grid Layout 위젯 드래그&드롭 이벤트 생성하기 (0) | 2023.07.12 |
---|---|
QSettings 사용 예제 코드 (0) | 2022.07.26 |
PyQt5 이미지 비율 맞추기 (0) | 2022.06.20 |
PyQt5 버튼 애니메이션 (0) | 2022.06.15 |
PyQt5 종료 Fade out 이벤트 (0) | 2021.07.08 |