
import os
import random
import getpass
import pickle
# 유저 정보를 저장하는 Dictionary 변수를 불러오기 위한 pickle
with open("data/user_info.pkl", "rb") as fr:
user = pickle.loads(fr.read())
# 메인 스트림을 분기를 조정하는 스위칭 변수
controller = "main"
# 현재 접속한 인원에 대한 정보, 딱히 쓸모는 없는 상태.
current_id = ""
def encoding_pw(pw):
"""
받은 문자열을 암호화 해주는 함수
:param pw: str, 비밀번호 문자열
:return en_pw: str, 암호화된 비밀번호 문자열
"""
en_pw = ""
range_1 = list(range(33, 39)) + list(range(48, 58))
range_2 = list(range(65, 91)) + list(range(97, 122))
for idx, ch in enumerate(pw):
if random.random() >= 0.5:
add_pw = chr(random.choice(range_1))
new_i = chr(ord(ch) + (idx % 3) * 2 + 1)
else:
add_pw = chr(random.choice(range_2))
new_i = chr(ord(ch) - (idx % 3) * 2 - 1)
en_pw += add_pw
en_pw += new_i
if random.random() >= 0.5:
en_pw += chr(random.choice(range_1 + range_2))
return en_pw
def decoding_pw(en_pw):
"""
암호화된 비밀번호를 복화화하여 원상복구 시키는 함수
:param en_pw: str, 암호화된 비밀번호
:return pw: str, 복화화된 비밀번호
"""
pw = ""
for idx, ch in enumerate(en_pw):
if idx % 2 == 1:
if ord(en_pw[idx - 1]) < 65:
de_i = chr(ord(ch) - ((idx//2) % 3)*2 - 1)
else:
de_i = chr(ord(ch) + ((idx // 2) % 3) * 2 + 1)
pw += de_i
return pw
def print_main_menu():
"""
메인화면을 UI 출력 함수
:return: None
"""
# print(user)
# print(encoding_pw("1q2w3e"))
print("1. 로그인\n2. 회원가입\n0. 종료")
def main_stream():
"""
메인화면에서의 흐름을 통제하는 함수
:return controller: str, 전체 흐름의 분기를 관장하는 변수
"""
while True:
os.system("cls")
print_main_menu()
usr_in = input("입력 : ")
if "1" in usr_in:
return "sign in"
elif "2" in usr_in:
return "sign up"
elif "0" in usr_in:
return "exit"
else:
os.system("cls")
input("잘못 입력했습니다!")
def sign_in_stream():
"""
로그인에서의 흐름을 통제하는 함수
:return controller: str, 전체 흐름의 분기를 관장하는 변수
:return tmp_user_info : tuple, 로그인한 대상의 정보를 전달해주는 tuple
"""
while True:
os.system("cls")
id_in = input("아이디 입력 : ")
if id_in == "exit":
return "main", None
pw_in = getpass.getpass("비밀번호 입력 : ")
if pw_in == "exit":
return "main", None
if user.get(id_in) is not None:
if decoding_pw(user.get(id_in)[0]) == pw_in:
tmp_user_info = (id_in, user[id_in][1])
return "sign in success", tmp_user_info
else:
os.system("cls")
input("아이디 혹은 비밀번호가 틀렸습니다!")
def print_sign_up(id_="", pw="", name=""):
"""
회원가입에서 현재 입력한 값을 보여주는 UI 출력 함수
:param id_: str, 현재 입력 받은 ID문자열, default=""
:param pw: str, 현재 입력 받은 비밀번호 문자열, default=""
:param name: str, 현재 입력 받은 이름 문자열, default=""
:return: None
"""
os.system("cls")
if not id_:
id_ = "---------"
if not pw:
pw = "---------"
if not name:
name = "---------"
print(f" I D : {id_}")
if pw != "---------":
print(f"Password: {len(pw)*'*'}")
else:
print(f"Password: {pw}")
print(f"N a m e : {name}")
def sign_up_stream():
"""
회원가입에서의 흐름을 통제하는 함수
:return controller: str, 전체 흐름의 분기를 관장하는 변수
"""
id_ = id_check()
if id_ == "exit":
return "main"
pw = pw_check(id_)
if pw == "exit":
return "main"
name = name_check(id_, pw)
if name == "exit":
return "main"
user[id_] = [encoding_pw(pw), name]
print_sign_up(id_, pw, name)
input("회원가입이 완료됬습니다!")
return "main"
def id_check():
"""
생성할 아이디를 입력받고 확인한 후 입력을 승인해주는 함수
:return usr_input: str, 입력받은 문자열 or 종료를 위한 'exit'문자열
"""
while True:
print_sign_up()
usr_input = input("생성할 아이디 입력 : ")
if usr_input == "exit":
return "exit"
if usr_input.isdigit():
os.system("cls")
input(f"'{usr_input}'은/는 숫자로만 이루어져 생성할 수 없습니다!")
elif usr_input in user.keys():
os.system("cls")
input(f"'{usr_input}'은/는 이미 존재합니다!")
else:
return usr_input
def pw_check(id_):
"""
생성할 비밀번호를 입력받고 확인한 후 입력을 승인해주는 함수
:param id_: str, 현재 입력값 출력을 위한 ID 변수
:return usr_input: str, 입력받은 문자열 or 종료를 위한 'exit'문자열
"""
switch_ = False
while not switch_:
print_sign_up(id_)
usr_input = getpass.getpass("새로운 비밀번호 입력 : ")
if usr_input == "exit":
return "exit"
switch_, msg = pw_make_check(id_, usr_input)
if not switch_:
os.system("cls")
input(msg)
continue
print_sign_up(id_, usr_input)
pw_recheck = getpass.getpass("비밀번호 확인 입력 : ")
if pw_recheck == "exit":
return "exit"
if usr_input != pw_recheck:
switch_ = False
os.system("cls")
input("비밀번호가 틀립니다!")
continue
return usr_input
def pw_make_check(id_, tmp_pw):
"""
비밀번호 입력시 세부적인 조건을 따로 분류한 함수
:param id_: str, ID에 대한 비교를 하기 위한 ID 변수
:param tmp_pw: str, 입력을 허가하기 전의 비밀번호
:return T/F: bool, 허용 가능한 비밀번혼지 아닌지 반환
:return msg: str, 반환 값에 대한 메세지
"""
uppers, lowers, numbers = False, False, False
repeat_module = ["", 0]
if not (8 <= len(tmp_pw) <= 15):
return False, "비밀번호는 최대 15글자, 최소 8글자여야 합니다."
if (id_ in tmp_pw) or (tmp_pw in id_):
return False, "비밀번호에 아이디값을 사용할 수 없습니다."
for i in tmp_pw:
if 48 <= ord(i) <= 57:
numbers = True
elif 65 <= ord(i) <= 90:
uppers = True
elif 97 <= ord(i) <= 122:
lowers = True
if not repeat_module[0] or repeat_module[0] != i:
repeat_module[0] = i
repeat_module[1] = 1
elif repeat_module[0] == i:
repeat_module[1] += 1
if repeat_module[1] == 3:
return False, "3번 연속되는 숫자는 사용할 수 없습니다."
if numbers and uppers and lowers:
return True, "done"
else:
return False, "적어도 1개 이상의 소문자, 대문자 숫자가 포함되어야 합니다."
def name_check(id_, pw):
"""
생성할 비밀번호를 입력받고 확인한 후 입력을 승인해주는 함수
:param id_: str, 현재 입력값 출력을 위한 ID 변수
:param pw: str, 현재 입력값 출력을 위한 비밀번호 변수
:return: str, 입력받은 문자열 or 종료를 위한 'exit'문자열
"""
while True:
print_sign_up(id_, pw)
usr_input = input("이름 입력 : ")
if usr_input == "exit":
return "exit"
if not (2 <= len(usr_input) <= 15):
os.system("cls")
input("이름은 최소 2글자, 최대 15글자여야합니다.")
return usr_input
while True:
"""
메인 스트림
"""
if controller == "main":
controller = main_stream()
elif controller == "sign in":
controller, user_info = sign_in_stream()
if controller == "sign in success":
current_id = user_info[0]
input(f"{user_info[1]}님 로그인 성공!")
controller = "main"
elif controller == "sign up":
controller = sign_up_stream()
elif controller == "exit":
os.system("cls")
input("프로그램을 종료합니다!")
exit()
with open("data/user_info.pkl", "wb") as fw:
fw.write(pickle.dumps(user))
감사합니다.
'광주인력개발원' 카테고리의 다른 글
<파이썬으로 8만대장경 작성하기> 개발 실패 <2023-05-01 최종> (0) | 2023.05.30 |
---|---|
<파이썬으로 8만 대장경 작성하기> 개발 계획서 [2023-04-27 시작] (0) | 2023.05.30 |
<개복치 키우기> 개발 완료 보고서 [2023-04-25 학습일지] (1) | 2023.05.30 |
<경주마와 아이들> 팀이 내주신 문제 풀이 중간 보고서 <2023-04-24 개발일지> (0) | 2023.05.30 |
for 반복문 사용하여 숫자 스무고개 만들기 [2023-04-21] (1) | 2023.05.30 |