원래 초기에는 서버 하나가 담당했기에 서버측에서 session을 사용하여서 로그인을 담당했기에 정보 저장의 주체가 server였다.
그러나 스마트폰의 보급 및 시대가 달라지면서 웹 서버 따로 두고 어플리케이션 서버 따로 두면서 일반적인 session을 이용한 로그인과정이 문제가 되기 시작했다. 또한 클라우드 서버가 생기면서 로그인 과정에 토큰을 이용한 로그인이 활성화되기 시작했다.
그래서 token을 이용하여 서버가 여러개인 사이트에 로그인을 하기 위해서는 token이 있는지 확인하기 위한 middleware가 필요하게 되었다.
그리고 token에 정보들을 보안때문에 암호화해서 보내는데, 그 방식으로는 JWT(Json Web Token)이 쓰인다.


컴퓨터는 기본적으로 2진법을 사용한다. 그런데, 이를 16진법으로 바꾸기 쉽기때문에 컴퓨터는 16진법을 사용한다. 2진법을 16진법으로 바꾸기 용이하기에 가독성도 높이고, 효율성도 높이기위해 컴퓨터에서는 16진법을 이용한다. 16진법 한자리가 2진법의 4단위와 같기 때문이다. 또한 64진법 또한 16진법에서 바꾸기 용이해서 많이 쓰인다.
https://jwt.io/

위의 사이트로 들어가면 토큰을 생성할 수 있다. 토큰의 형식은 다음과 같다.
header.playload.signature
위의 사이트에서 토큰을 구해보면 .으로 각 항목이 구분된다는 것을 알 수 있다.

let header =
{
"alg":"HS256",//token 알고리즘
"typ" : "JWT"//token이름
}
console.log(JSON.stringify(header));//객체를 string으로 바꾸는 함수{"alg":"HS256","typ":"JWT"}
let encodeheader = Buffer.from(JSON.stringify(header)).toString('base64').replace('=','');
JSON.stringify()
위의 함수는 객체를 string으로 바꿔주는 함수이다.
위의 console.log(JSON.stringify(header))의 결과값은
{"alg":"HS256","typ":"JWT"}
위와 같이 나오는데, 전체가 string형식이다.
JSON.stringify(header).alg
와 같이 쓸 수 없다.
8bit binary data를 문자코드에 영향을 받지 않는 ASCII 코드 문자들로 이루어진 64진법으로 바꾸는 인코딩 방식이다.
위의 함수가 33%의 확률로 padding이 일어난다고 한다. 그리하여서 이걸 써서 =를 공백으로 바꾸는 함수이다.
payload=
{
"sub":"123456",
"name":"John Doe",
"user":"web7722",
"iat":1516239022
}
let encodepayload = Buffer.from(JSON.stringify(payload)).toString('base64').replace('=','');
코드가 header와 같기에 설명은 생략하겠다.
let signature = crypto.createHmac('sha256',Buffer.from('princessmaker'))
.update(`${encodeheader}.${encodepayload}`)//header.payload
.digest('base64')//64비트로 바꿔준다.
.replace('=','');
signature부분에서 암호화가 이루어진다. 여기서 암호화 library인 crypto가 쓰인다.
createHmac sha256은 sha256과는 다르다. 주어진 비밀키와 함께 해싱을 하고 해싱된 결과물을 비밀키와 함께 또 다시 해싱한다. 그리하여 보안성을 높인다.
형식은 다음과 같다.
crypto.createHmac('암호화형태(string)','암호화키(binary값 형태)').update('평문').digest('output type')
그리하여 완성된 토큰은 다음과 같은 형태로 입력하면 된다.
${encodeheader}.${encodepayload}.${signature2}