WIL

이노베이션 캠프 1주차 WIL

yougeun 2022. 6. 26. 20:10
728x90

파이참으로 첫 번째 프로젝트를 만들면서  필수과제인 JWT를 이용하여 회원가입과 로그인을 구현하였다.

회원가입 시 비밀번호를 해쉬값으로 변환하여 DB에 저장하여 해쉬값이 유출되더라도 비밀번호를 알 수 없도록 하게 했다.

@app.route('/sign_up/save', methods=['POST'])
def signup_save():
    id_receive = request.form['id_give']
    password_receive = request.form['password_give']
    nickname_receive = request.form['nickname_give']
    password_hash = hashlib.sha256(password_receive.encode('utf-8')).hexdigest()
    doc = {
        "id": id_receive,  # 아이디
        "password": password_hash,  # 비밀번호
        "nickname": nickname_receive,  # 프로필 이름 기본값은 아이디
    }
    db.users.insert_one(doc)
    return jsonify({'result': 'success'})

 

메인 페이지에서는 jwt 토큰이 없으면 웹페이지의 콘텐츠를 이용할 수 없게 하여 필수로 회원가입과 로그인을 하게 하였다.

jwt토큰은 'my token'이라는 이름으로 쿠키값으로 저장되게 만들었으며 쿠키값을 알더라도 SECRET_KEY를 모르면 복호화가 불가능하게 하였다.

 

@app.route('/', methods=["GET"])
def home():
    token_receive = request.cookies.get('mytoken')
    try:
        payload = jwt.decode(token_receive, SECRET_KEY, algorithms=['HS256'])

        return render_template('index.html',token=token_receive)
    except jwt.ExpiredSignatureError:
        return render_template('index.html')
    except jwt.exceptions.DecodeError:
        return render_template('index.html')

 

로그인 시 사용자가 적은 아이디와 비밀번호를 가져와 비밀번호를 해쉬값으로 변환한 후  DB와 비교하여  유저라면 아이디 값을 이용하여 쿠키를 발행해주고 유저가 아닐 시 아이디와 비밀번호가 일치하지 않는다는 메시지를 클라이언트에 주도록 하였다.

 

@app.route('/sign_in', methods=['POST'])
def sign_in():
    # 로그인
    id_receive = request.form['id_give']
    password_receive = request.form['password_give']

    pw_hash = hashlib.sha256(password_receive.encode('utf-8')).hexdigest()
    result = db.users.find_one({'id': id_receive, 'password': pw_hash})
    if result is not None:
        payload = {
            'id': id_receive,
            'exp': datetime.utcnow() + timedelta(seconds=3600)  # 로그인 24시간 유지
        }
        token = jwt.encode(payload, SECRET_KEY, algorithm='HS256')
        print(token)

        return jsonify({'result': 'success', 'token': token})
    # 찾지 못하면
    else:
        return jsonify({'result': 'fail', 'msg': '아이디/비밀번호가 일치하지 않습니다.'})

클라이언트에서 서버에 쿠키값을 보내면 쿠키값을 복호화하여 유저 정보를 알아낸 후 그 유저 정보를 활용해 DB에 원하는 정보를 저장하게끔 함으로써 개인정보보안에 더 힘쓰었다.

@app.route('/quiz/savetime', methods=['POST'])
def quiz_savetime():
    time_receive = request.form['time_give']
    cookie_receive = request.form['cookie_give']
    review_receive = request.form["review_give"]
    print(cookie_receive)
    id = jwt.decode(cookie_receive, SECRET_KEY, algorithms='HS256')["id"]
    user = db.users.find_one({'id': id})

    doc = {
        "nickname": user["nickname"],
        "totaltime": int(time_receive),
        "review": review_receive
    }
    db.ranking.insert_one(doc)
    return jsonify({'result': 'success'})

 

로그인 시 이러한 오류가 발생했었는데 파이썬 패키지중인 하나인 PyJWT의 버전 차이로 인해 발생한다는 이유를 알게 되었다. 이러한 이유가 발생한다면 아래의 그림처럼 수정하거나 PyJWT의 버전을 바꿔본다면 오류가 없어질 것이다.

로그인시 오류 코드

token = jwt.encode(payload, SECRET_KEY, algorithm='HS256').decode('utf-8')

오류가 일어난 코드

token = jwt.encode(payload, SECRET_KEY, algorithm='HS256')

수정 후 코드

 

 

 

그리고 서버와 클라이언트의 모든 통신은 REST API를 이용하여 통신하였다. REST API에서 GET과 POST를 이용하여 구현하였는데 GET은 서버에서 데이터를 받아올 때 사용하였고 POST는 서버의 데이터를 변경할 때 사용하였다. 로그인 시 GET과 POST를 어떤 것을 사용할지 고민이 있었는데 인터넷에 검색해본 결과 URL이 남지 않는 POST가 안전하다고 하여 POST로 통신하였다. 

 

 

function sign_in() {
    let id = $("#input-id").val()
    let password = $("#input-password").val()

    if (id == "") {
        $("#help-id-login").text("아이디를 입력해주세요.")
        $("#input-id").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: {
            id_give: id,
            password_give: password,
        },
        success: function (response) {
            if (response['result'] == 'success') {
                $.cookie('mytoken', response['token'], {path: '/'});
                window.location.replace("/")
            } else {
                alert(response['msg'])
            }
        }
    });
}

로그인 시 POST를 이용한 RESTAPI통신

728x90