항해99 첫주차
회원가입 / 로그인 페이지 구현
로그인한 사용자는 어떻게 계속 로그인 상태를 유지하면서 권한이 필요한 우리 서비스를 돌아다니는걸까?
JWT 는 회원 로그인이 완료 되었을때 발행되는 토큰을 말한다.
JWT에는 암호화 된 회원정보가 들어있으며 복호화를 통해 사이트내의 서비스를 사용할 수 있는지
확인 (인가 : Authorizationathon ) 하는데 사용한다.
JWT는 JSON Web Token 의 약자로 전자서명 된 URL-safe : URL로 이용할 수 있는 문자로만 구성된 JSON 이다.
클라이언트와 서버, 서비스와 서비스 사이 통신 시 권한 인가(Authorization)를 위해 사용하는 토큰이다
JWT는 서버와 클라이언트 간 정보를 주고 받을 때 Http request header 에 JSON 토큰을 넣은 후 서버는 별도의 인증 과정없이 헤더에 포함되어 있는 JWT 정보를 통해 인증한다. 이 인증 과정을 통해 사용자는 로그인 상태로 서비스를 돌아다닐 수 있다.
# 따로 정리할 정보
Http request header
JWT 이란 ? JSON Web Token
JSON포맷을 이용하여 사용자에 대한 속성을 지정하는 Web Token이다
JWT 구조
JWT는 헤더(header), 정보(payload), 서명(signature) 구조로 이루어져 있다.
HEADER . PAYLOAD . SIGNATURE헤더 내용 서명 . |
HEADER
타입(JWT)과 알고리즘(BASE64 같은)을 담는다.
{
"alg": "HS256", // alg: HS256 해쉬 알고리즘
"kid": "Key ID" // Private key ID (구글 API에서는 필수 사항)
}
# URL-safe : URL에서 파라미터로 사용할 수 있도록 한 문자
JWT를 검증하는데 필요한 정보를 가진 JSON 객체는 Base64 URL-Safe 인코딩된 문자열이다.
헤더(Header)는 JWT를 어떻게 검증(Verify)하는가에 대한 내용을 담고 있다.
참고로 alg는 서명 시 사용하는 알고리즘이고, kid는 서명 시 사용하는 키(Public/Private Key)를 식별하는 값이다.
alg는 헤더를 암호화 하는 것이 아니고, signature를 해싱하기 위한 알고리즘을 지정하는 것이다
( 해싱과 암호화는 비슷한 것 같지만 다르대요 !!!!!!! 그 개념까지는...... 나중에 정리할게 너무많네요 히...)
PAYLOAD
JWT의 내용으로 유저정보(id같은)와 만료기간이 객체형으로 담긴다.
토큰에서 사용할 정보의 조각들인 클레임(Claim)이 JSON (key,value)형태로 다수의 정보를 넣을 수 있다
클레임은 JWT에 대한 내용(클라이언트의 정보, 생성 일시 등)이나 클라이언트와 서버 간 주고 받기로 한 값들로 구성된다.
등록된 클레임(Registered Claim)
등록된 클레임은 토큰 정보를 표현하기 위해 이미 정해진 종류의 데이터들로,
모두 선택적으로 작성이 가능하며 사용할 것을 권장한다.
또한 JWT를 간결하게 하기 위해 key는 모두 길이 3의 String이다.
- iss: 토큰 발급자(issuer)
- sub: 토큰 제목(subject)
- aud: 토큰 대상자(audience)
- exp: 토큰 만료 시간(expiration), NumericDate 형식으로 되어 있어야 함 ex) 1480849147370
- nbf: 토큰 활성 날짜(not before), 이 날이 지나기 전의 토큰은 활성화되지 않음
- iat: 토큰 발급 시간(issued at), 토큰 발급 이후의 경과 시간을 알 수 있음
- jti: JWT 토큰 식별자(JWT ID), 중복 방지를 위해 사용하며, 일회용 토큰(Access Token) 등에 사용
SIGNATURE
header, payload를 인코딩 한 값을 합친뒤 SECRET_KEY로 해쉬한다.
JWT
점을 구분자로 해서 헤더, 페이로드, 서명을 합치면 JWT가 완성된다.
// 토큰에는 [유저 정보]와 [secret key], [적용하고자 하는 알고리즘]을 넣어서 발행한다.
// payload 안에는 사용자로부터 받은 아이디의 내용과
// 로그인을 유지시키는 시간이 설정되어있다
// 시크릿키는 'secretkey'이며 'HS256' 알고리즘을 사용해 토큰을 발행하겠다는 명령어 이다.
import jwt
payload = {
'id': username_receive,
'exp': datetime.utcnow() + timedelta(seconds=60*60*24) # 로그인 24시간 유지
}
token = jwt.encode(payload, 'secretKey', algorithm='HS256')
추가설명
datetime.utcnow( ) : 현재 시간을 불러오는 메서드
timedelta( ) : 특정 시간을 더하고 뺄때 사용하는 메서드
timedelta는 인자로 seconds, hours, days, weeks 를 받고, '='를 넣어서 시간을 표현
현재시간 기준 3일 후를 유효기간으로 사용하고 싶다면 timedelta(days=3)을 더해주면 되고,
3주면 timedelta(weeks=3)을 넣어주면 된다
months나 years는 좀 다르게 아래처럼 사용함
from dateutil.relativedelta import relativedelta
exp = datetime.utcnow() - relativedelta(months=3)
// 토큰을 jwt로 디코딩하면 기존에 입력했던 유저정보가 반환된다.
def home():
token_receive = request.cookies.get('mytoken')
try:
payload = jwt.decode(token_receive, SECRET_KEY, algorithms=['HS256'])
#사용자정보 보여주기/ payload로부터 실제 유저의 정보를 가져온다
user_info = db.users.find_one({"username": payload["id"]})
return render_template('index.html', user_info=user_info)
// 구현된 JWT => mytoken으로 쿠키에 저장해서 사용
// HEADER . PAYLOAD . SIGNATURE => . 으로 구분되는 부분을 ENTER함.
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.
eyJpZCI6InRoZHVkMTExMSIsImV4cCI6MTY0MjM5MjQwMX0.
s6PHHnTPCJ7SABoL-B6SFJNilcxuCbhyEhd0xtWl9rI
JWT는 헤더의 alg, kid 속성과 공개 키를 이용해 검증할 수 있다. 서명 검증이 성공하면 JWT의 모든 내용을 신뢰할 수 있게되고, 페이로드의 값으로 접근 제어나 원하는 처리를 할 수 있게된다.
아 그래서
JWT를 어떻게 쓰냐면,
- 유저가 로그인 했을때 입력값이 DB의 회원정보와 일치할때 JWT를 발급한다.
- 프론트엔드에서는 JWT를 로컬/세션스토리지에 저장
- 유저가 회원인증이 필요한 서비스에 접근했을때,
프론트는 요청을 보낼때 header, authorization에 토큰값을 담아 보낸다. - 백엔드 에서는 받은 토큰값을 복호화 하여 유저정보를 확인
- DB에서 해당정보가 있는지 확인, 있다면 해당 서비스를 이용할수 있도록 함
'개발공부_Blog > HTML-CSS' 카테고리의 다른 글
JWT / COOKIE / SESSION 차이점 (0) | 2022.01.16 |
---|---|
JWT ERROR (0) | 2022.01.16 |
css - img사이즈조절 (0) | 2021.12.20 |
HTTP 프로토콜 (0) | 2021.11.29 |
CSS - position (0) | 2021.11.27 |
댓글