Session & Cookie:서버에서 사용할 수 있는 전통적인 방법
Session?? : 사용자의 세션을 서버에 보관하고 있는 방법
첫번째로 클라이언트가 서버로 로그인을 하게 된다면
서버는 사용자의 데이터베이스에 있는 id/password가 일치하는지 먼저 확인
존재하는 유용한 사용자라면 서버에서 세션(userId, sessionId, expiration)을 만든다
만든 세션을 별도의 세션이라는 데이터베이스에 저장을 하게 된다.
데이터베이스일수도 있고 아니면 파일 시스템에 저장을 하거나 또는 메모리 상에 보관할수도 있다. 통상적으로는 데이터베이스에 저장을 한다.
이렇게 세션을 만들어서 세션 데이터베이스에 추가한 다음에 서버는 클라이언트에게 세션과 관련된 정보를 보내준다
보통은 쿠키에 정보(Cookie:sessionId, httpOnly) 를 넣어서 보내게 된다. httpOnly 라는 옵션을 주게 되면 해당하는 쿠키는 브라우저에 의해서만 읽을수 있다. 클라이언트에서 자바스크립트나 프로그램내에서 읽을수 없고 브라우저에서만 읽어서 다시 서버에 보낼 수 있는 조금 안전한 방식으로 보내게 된다
이 쿠키를 이용해서 클라이언트가 서버에 다른 요청을 할때 쿠키 정보를 브라우저에서 자동으로 포함해 주므로 (Cookie:sessionId)
클라이언트에서 보내준 세션아이디를 통해서 세션 데이터베이스에 존재하는 세션아이디인지 혹시 만료된 세션은 아닌지 검토한 다음에 유효하다면 이 세션아이디를 통해서 사용자가 누구인지 파악을 해서 관련된 데이터를 클라이언트에 보내줄 수 있다
세션 방식의 장점:
1. 세션이라는 데이터베이스에 모든 세션의 정보를 보관하고 있으므로 신뢰할 수 있는 데이터가 있다.
2. 쿠키를 사용하기 때문에 서버에서 보낼때도 쉽고 클라이언트에서 별도로 처리를 하지 않아도 브라우저에서 자동으로 해줄수 있으므로 간단하게 구현할 수 있다. httpONly라는 옵션을 사용할 경우 안전하게 보안성을 높여서 사용할 수 있다.
3. 사용자에게 사용자의 정보를 보내는 것이 아니라 세션아이디를 보내고 이 사용자가 누구인지 다른 정보를 주고받지 않으므로 안전하다고 볼수 있다
세션 방식의 단점 :
1. Stateful : 서버에서 시시각각 변하는 로그인하는 사용자에 대해서 세션의 정보를 보관하고 있으므로 서버에 상태가 있다. 이것 때문에 서버를 확장해서 여러개의 서버에서 동작을 하던지 아니면 마이크로서비스를 하는 경우에 한 서버에 세션을 보관하고 있으므로 다양한 많은 서버들이 이 세션의 정보를 확인하기 위해서 하나의 서버에 접속을 해서 네트워크 요청을 해야한다 그 말은 클라이언트의 요청을 처리하기 위해서 내부적으로 여러가지 네트워크 요청을 해야해서 시간이 많이 걸릴수도 있다. 분산형 시스템으로 서비스를 잘 디자인했음에도 불구하고 세션때문에 성능이 좋지 않은 경우도 발생한다.
JWT(JSON Web Token)2010에 만들어짐???
:JSON이라는 파일 안에 필요한 모든 데이터를 넣어서 이것을 주고 받고 할 수 있다.
(JSON을 이용해서 웹 토큰을 주고 받는 것을 말한다.)
base64urlEncodin(header).base64urlEncoding(payload).base64urlEncoding(signature)
안전한 이유는 secret을 통해서 인코딩을 하기때문에 정보의 유효성을 확인할 수 있다.
JSON이라는 오브젝트 베이스 안에
{Header, Payload, Signature} 로 나누어져 있다
이 안에 사용자에 대한 인증 정보를 담고 있다.
{Header: {"alg": "H256", "typ":"JWT"},
Payload(우리가 전송하고 주고받고 싶은 다양한 데이터-인코딩됨),
Signature(인코딩한 Header & Payload뿐만 아니라 이것을 인코딩하기 위해서 사용하는 서버의 비밀키(secret)를 이용해서 함께 인코딩을 해놓음)}
이렇게 서버에서만 알고 사용하는 secret과 함께 인코딩을 해놓음으로써 나중에 사용자가 악의적으로 payload에 있는 정보를 바꿀때 Signature에 있는 정보를 통해서 해당 내용이 변경되었는지 변경되지 않았는지를 확인할 수 있다.
첫번째로 클라이언트가 서버로 로그인을 하게 된다면
서버는 사용자의 데이터베이스에 있는 id/password가 일치하는지 먼저 확인
유효한 사용자라면
사용자의 {userId,claims,expiration} 우리가 원하는 정보를 묶어서 JWT를 만들게 된다
만들어진 JWT를 사용자에게 보내주고 추후에 요청하는 모든 API 요청에 대해서 클라이언트가 서버에서 받은 이 JWT를 헤더에 포함해서 서버로 보내게 되면
서버는 클라이언트에서 받은 이 JWT를 이용해서 전달받은 JWT가 유효한지 유효하지 않는지 수정이 되었는지 되지 않았는지 만료되지 않았는지 여기 들어있는 사용자의 정보가 정확한지 정확하지 않은지 유효성 검사를 한 다음에 해당하는 데이터를 클라이언트에 보낸다
JWT의 장점!!!
1. NO State!!! : 한번 json으로 만들어서 클라이언트에 보내주고 다시 검증하는 것만 하면 되기때문에 별도의 상태는 필요하지 않다. 그렇기 때문에 서버를 확장하거나 마이크로 서비스를 이용하거나 분산형 시스템으로 만들어도 서로 서버간의 네트워크를 통해서 사용자의 검증을 하지 않아도 이 JWT를 만들고 해독할 수 있는 동일한 secret키만 가지고 있으면 된다
JWT의 단점!!!
{JWT} 이 자체가 단점이 될 수 있다
서버와 클라이언트 간에 계속 끊임없이 이 중요한 {JWT}에 대해서 서로 주고 받고 할 수 있다.
만약 영원히 만료되지 않는 {JWT}를 서로 주고 받는다면 해커가 이 정보(Header:Authorization:Bearer JWT)를 그대로 가져가서 악용할 수 있기 때문
그래서 이 {JWT}를 사용할 때도 보안에 유념을 해야한다.
사용자의 아이디와 패스워드를 데이터 베이스에 저장할 때 보다 안전하게 보관하는 방법
bcrypt : password를 안전하게 보관할 수 있도록 password를 해싱하는 알고리즘 (password-hashing function) - 암호화만 가능한 방식
rainbow table : 특정 문자열을 암호화한 것들을 테이블로 만들어서 원래의 암호를 유추할 수 있게 만들어 놓은 테이블- 해커: 가지고 있는 테이블의 갯수가 salt의 갯수만큼 늘어나므로 해독하는데 어렵게 만든다 해킹을 쉽게 하지 못하도록 salt가 필요하다.
사용자가 가입할 때 입력하는 아이디와 패스워드를 그대로 데이터 베이스에 저장을 하면 해커가 우리 서버에 있는 데이터베이스의 정보를 읽어서 사용자 아이디와 패스워드의 정보를 훔쳐갈 수 있다
bcrypt를 이용해 잘만들어진 암호화된 알고리즘으로 해싱을 해서 만든 패스워드를 데이터 베이스에 저장을 해둘 수 있다
bcrypt의 값은 4부분으로 나눠진다
1. Algorithm : 알고리즘 식별자. ''는bcrypt를 뜻한다
2. Cost factor : 얼마나 많은 복잡도로 암호화를 했는지 암호화를 위한 비용
3. Salt : 우리가 원하는 길이만큼의 더 랜덤한 것들을 이용해서 암호화를 복잡하게 만드는 것 (base64-encoded)
4. Hash : salting과 키 스트레칭 후 해시 값(base64-encoded)
npm i bycrypt