JWT(Json web Token)은 토큰 기반 인증 방식으로, 클라이언트의 세션 상태를 저장하는 게 아니라 필요한 정보를 토큰 body에 저장해 클라이언트가 가지고 있고 그것을 증명서처럼 사용합니다.
JWT의 기본 구성은 3가지로 나눠집니다.
JWT는 자체 내에 정보를 가지고 있기 때문에 클라이언트가 해독해 정보를 볼 수 있지만 받는 자가 secret 키를 알고 있어야만 수정이 가능합니다. 그리고 JWT 인증 방식을 채용할려면 기한 조절이 중요합니다. 만약 수명이 길면 해커에게 해독될 위험이 있고 수명이 짧다면 토큰이 만료될때마다 로그인을 다시 해줘야됩니다.
일단 아주 간단하게 테스트하기위해서 저는 버튼 하나만 구현하였습니다.
<button onclick="loginClick()">로그인</button>
이 버튼을 클릭하게 되면 자동으로 로그인이 되게 코드를 만들었습니다.
버튼클릭이벤트 함수와 flask의 login부분을 보여드리겠습니다.
클릭이벤트
function loginClick(){
$.ajax({
type: "POST",
url: "http://localhost:5000/login",
data: {id:'Minsu', pw:'123456'},
success: function(response){
console.log(response)
}
})
}
admin_id = "Minsu"
admin_pw = "123456"
SECRET_KEY = 'apple'
@app.route("/login", methods=['POST'])
def login_proc():
print(request.form)
input_data = request.form
user_id = input_data['id']
user_pw = input_data['pw']
# 아이디, 비밀번호가 일치하는 경우
if (user_id == admin_id and
user_pw == admin_pw):
payload = {
'id': user_id,
'exp': datetime.utcnow() + timedelta(seconds=60) # 로그인 24시간 유지
}
token = jwt.encode(payload, SECRET_KEY, algorithm='HS256')
return jsonify({'result': 'success', 'token': token})
# 아이디, 비밀번호가 일치하지 않는 경우
else:
return jsonify({'result': 'fail'})
코드를 보시면 POST로 {id:'Minsu', pw:'123456'} 값을 받아 오게 됩니다. 받아온 id와 pw는 항상 admin_id와 pw랑 같게 설정을 해주었습니다. 그래서 payload의 id는 해당 토큰의 고유성을 식별하기 위한 정보이고 exp는 해당 토큰의 만료일자 입니다. 즉 payload를 설정하고 jwt.encode()함수에 우리가 설정한 payload와 JWT 토큰을 생성하는데 필요한 시크릿 값과 사용할 암호화방식을 선택하고 토큰을 생성하게 됩니다.
즉 비밀번호와 아이디가 일치하는경우 이 토큰값을 넘겨주고 아닌경우에는 result:fail을 보내주게 됩니다.
클라이언트의
function(response){
console.log(response)
}
이부분을 로그를 찍게되면
토큰값이 나오는것을 확인할 수 있습니다.
자 이제 토큰값으로 인증을 해보도록 하겠습니다.
function loginClick(){
$.ajax({
type: "POST",
url: "http://localhost:5000/login",
data: {id:'Minsu', pw:'123456'},
success: function(response){
console.log(response)
let access_token = response['token']
console.log((access_token))
if (response['result'] == 'success') {
$.cookie('mytoken', response['token'], {path: '/'});
window.location.replace("/mainPage")
} else {
alert(response['msg'])
}
}
})
}
cookie에 토큰값을 저장하는 코드를 작성한후에 mainPage으로 페이지 이동을 시킵니다.
따라서 app.py의
@app.route('/mainPage')
def home2():
token_receive = request.cookies.get('mytoken')
try:
payload = jwt.decode(token_receive, SECRET_KEY, algorithms=['HS256'])
print(payload)
return render_template('main.html')
except jwt.ExpiredSignatureError:
return redirect("http://localhost:5000/")
except jwt.exceptions.DecodeError:
return redirect("http://localhost:5000/")
이부분이 동작하게 되는데
cookie에 저장되어있는 token값을 꺼낸뒤에 token_receive에 저장합니다
그리고 payload = jwt.decode(token_receive, SECRET_KEY, algorithms=['HS256']) 이 부분에서 token값을 다시 id값으로 바꿔줍니다 이때 만약 만료된 토큰이거나 가지고 있는 토큰이 문제가 있다면 다시 버튼이 있는 페이지로 redirect시켜줍니다.
JWT 인증 방식이 여기서 끝은 아니지만 오늘 큰 틀이라도 배운것 같아서 기분이 좋네요...