그동안 정신없어서 TIL을 놓쳤다. 윽
웹 개발 팀프로젝트가 시작했다.
그동안은 UI만 클론했다고 하면 이번에는 실제 서비스를 제공할 수 있는 웹 페이지를 개발하는 것이 목표.
내가 맡은 부분은 회원가입, 로그인, 로그아웃 부분 백엔드 개발이다.
크 우리 갓팀원들이 만든 프론트엔드 너무너무 이쁘다.
JWT가 무엇인지에 관한 자세하고 좋은 글들이 너무 많기 때문에
나는 내가 회원가입 기능을 구현하기위해 생각해야했던 간단한 로직을 정리해봤다.
HS256
알고리즘 사용)따라서 이 4가지의 과정을 중점적으로 기억하면서 기능 구현을 위한 코드를 작성했다.
유저가 입력한 값을 해쉬화하고 값을 DB값과 비교후 토큰부여, 혹은 DB에 저장(회원가입)
# 회원가입
@app.route('/sign_up/save', methods=['POST'])
def sign_up():
username_receive = request.form['username_give']
password_receive = request.form['password_give']
nickname_receive = request.form['nickname_give']
password_hash = hashlib.sha256(password_receive.encode('utf-8')).hexdigest() # password 해쉬화 함수
doc = {
"username": username_receive, # 아이디
"password": password_hash, # 비밀번호
"nickname": nickname_receive, # 닉네임
"profile_pic": "", # 프로필 사진 파일 이름
"profile_pic_real": "profile_pics/profile_placeholder.png", # 프로필 사진 기본 이미지
"profile_info": "" # 프로필 한 마디
}
db.users.insert_one(doc) # 유저가 입력한 아이디 pw 닉네임을 DB에 저장
return jsonify({'result': 'success'})
# 로그인서버
@app.route('/sign_in', methods=['POST'])
def sign_in():
# 로그인
username_receive = request.form['username_give']
password_receive = request.form['password_give'] # 유저가 아이디 pw 입력
pw_hash = hashlib.sha256(password_receive.encode('utf-8')).hexdigest() # 유저가 입력한 pw를 해쉬화
result = db.users.find_one({'username': username_receive, 'password': pw_hash})
# 아이디와 유저가 입력한 해쉬화된 pw가 DB에 저장되어 있는 해쉬화된 pw와 일치하는지 확인
if result is not None: # 일치한다면
payload = {
'id': username_receive,
'exp': datetime.utcnow() + timedelta(seconds=60 * 60 * 24) # 로그인 24시간 유지
}
# 유저 아이디와 유효기간을 담고 있는 payload 생성
token = jwt.encode(payload, SECRET_KEY, algorithm='HS256')
# jwt기반 토큰 생성
return jsonify({'result': 'success', 'token': token})
# 토큰을 유저에게 부여
# 찾지 못하면
else:
return jsonify({'result': 'fail', 'msg': '아이디/비밀번호가 일치하지 않습니다.'})
유저가 입력한 ID, PW를 로그인, 회원가입 함수에 연결하는 부분
function sign_up() {
let username = $("#input-username").val()
let password = $("#input-password").val()
let nickname = $("#input-nickname").val()
let password2 = $("#input-password2").val()
console.log(username, nickname, password, password2)
if ($("#help-id").hasClass("is-danger")) {
alert("아이디를 다시 확인해주세요.")
return;
} else if (!$("#help-id").hasClass("is-success")) {
alert("아이디 중복확인을 해주세요.")
return;
}
if (password == "") {
$("#help-password").text("비밀번호를 입력해주세요.").removeClass("is-safe").addClass("is-danger")
$("#input-password").focus()
return;
} else if (!is_password(password)) {
$("#help-password").text("비밀번호의 형식을 확인해주세요. 영문과 숫자 필수 포함, 특수문자(!@#$%^&*) 사용가능 8-20자").removeClass("is-safe").addClass("is-danger")
$("#input-password").focus()
return
} else {
$("#help-password").text("사용할 수 있는 비밀번호입니다.").removeClass("is-danger").addClass("is-success")
}
if (password2 == "") {
$("#help-password2").text("비밀번호를 입력해주세요.").removeClass("is-safe").addClass("is-danger")
$("#input-password2").focus()
return;
} else if (password2 != password) {
$("#help-password2").text("비밀번호가 일치하지 않습니다.").removeClass("is-safe").addClass("is-danger")
$("#input-password2").focus()
return;
} else {
$("#help-password2").text("비밀번호가 일치합니다.").removeClass("is-danger").addClass("is-success")
}
$.ajax({
type: "POST",
url: "/sign_up/save",
data: {
username_give: username,
password_give: password,
nickname_give: nickname
},
success: function (response) {
alert("회원가입을 축하드립니다!")
window.location.replace("/login")
}
});
}
<!--================로그인==================-->
function sign_in() {
let username = $("#input-username").val()
let password = $("#input-password").val()
if (username == "") {
$("#help-id-login").text("아이디를 입력해주세요.")
$("#input-username").focus()
return;
} else {
$("#help-id-login").text("")
}
if (password == "") {
$("#help-password-login").text("비밀번호를 입력해주세요.")
$("#input-password").focus()
return;
} else {
$("#help-password-login").text("")
}
$.ajax({
type: "POST",
url: "/sign_in",
data: {
username_give: username,
password_give: password
},
success: function (response) {
if (response['result'] == 'success') {
$.cookie('mytoken', response['token'], {path: '/'});
window.location.replace("/")
} else {
alert(response['msg'])
}
}
});
}
유저가 ID,PW를 입력하는 부분
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- JS -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="static/script.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.js"></script>
<!-- 회원가입 버튼 -->
<label for="input-username" style="margin-top: 10px"></label>
<input type="text" class="form-control" id="input-username" placeholder="ID" style="margin-bottom: 10px">
<input type="password" class="form-control mx-sm-3" id="input-password" placeholder="PASSWORD" aria-describedby="passwordHelpInline">
<button type="button" class="btn btn-primary" onclick="sign_in()">로그인</button>
<button onclick="sign_up()">회원가입</button>
백엔드를 기능을 구현하는 과정이 가장 어렵고 힘들었지만,
구현된 기능을 팀원이 만들어놓은 프론트엔드 페이지에 연동시키는 과정에서
아직 자잘하게 연동되지 않은 기능들이 하나 둘 생겨 그 과정도 쉽지 않다.
확실히 로직을 이해하고 논리적으로 사고하는 힘이 필요하겠지만 아직은 좀 벅찬 것이 사실 :)
현재는 이것저것 값을 바꿔보고, 프린트해보면서 주먹구구 식으로 끼워맞추기 식으로 구현하고 있다 😂
뭐 하다보면 늘겠지 😏