로그인 프로토컬:
로그인 페이지에서 post로그인을 한다. body로 (x-www-form-urlencoded)로 날아간다.
처리하는 스프링 쪽에선 id와 password가 객체로 날아와
컨트롤러가 받아 @PostMapping등 하고
id와 password는 서블릿이라고 하는 HttpRequest라고 하는 객체에 들어있다. HttpRequest을 직접 제어하면 안좋으니까 이것의 추상화된 형태를 이용한다. id/pwd를 db에 저장된 값과 비교를 한다.
db를 읽어온것도 추상화가 되어있어, 스프링 jpa로 추상화되어있다. newUser과 dbUser가 비교해서 같다면, Session이란 객체를 이용해 session에 addUser한다. 세션은 일종의 일급 컬렉션이고, map이라고 할 수 있다. key-value로 추가하는데, key는 sessionedUser value는 user이다.
세션은 임시저장소인데, 서버에서 사용하기 공유가?
두명 로그인하면 두명 세션이 생긴다. 각 세션은 독립적이다. sessionedUser로 키를 넣어도, 각 세션은 그 사용자용 전용 스토리지이다.로그인하면 세션에 로그인정보가 담기는데, 전부 담을 필요없고 pwd는 안담아도 된다. 필수적인 정보만 세션에 담긴다. id만 담고 매핑하면 좋지 않고, id와 사용자에게 필요한 (사용자 한명의 데이터를 처리하기 위해 필요한) 정보를 담는다.
post엔 렌더링할 뷰가 없기 때문에 return하면 안되고, 안좋고 redirect시켜줘야한다. 일반적인 사이트는 메인으로 redirect하면좋다.
DTO객체에 리퀘스트를 담아 처리하라고 하는데, 리뷰어들이 이런 주장을 하는 이유는? 리뷰어들이 enterprise에서 일하기 때문에 그런거다...
그러면 실제 http response에는?
세션 사용자와 client
client
server
로그인하면 client에서 server로 dto가 가고,
server에선 repository에서 꺼내 dto와 비교해 매치이 되면 세션id를 session에 담아 client로 응답을 보낸다. client는 이것을 브라우저 어딘가에 저장해두고, 서버와 계속 주고받는다.
http는 무상태이다.
로그아웃하면 sessionId를 지워준다. session에서 user지우고, 브라우저에서는 세션정보를 보안때문에 저장하지 않고 sessionId만 저장한다. 서버세션은 모든 중요한 정보를 저장한다. 세션 정보는 메모리에 저장된다.
세션 저장하고싶으면 sessionrepository에 저장하기 쉽고, 단점은 느리다. 소규모 회사는 메모리에 세션을 저장하는데, 세션을 메모리에 저장핤없는 경우는 사용자가 너무 많은 경우 메모리로 안된다.
메모리로 세션을 담기 어려우려면, 사용자가
사용자 많아지면 세션 db쓸수밖에없다. 너무 많은 정보 저장할 수없고 필수정보만 저장한다. 브라우저에도 세션 id등을 저장해야하는데, 어디에 저장하냐면 쿠키가 저장소이다. (헨젤과 그레텔에서 쿠키로 흔적 남기듯이) .. 쿠키집 뜯어먹으면 없어지듯이 보안에 취약하다.
사이트별로 쿠키가 있다.
면접에서 쿠키와 세션의 차이가 무엇이냐 물어보면 자바와 자바스크립트만큼 다르다고 하면 된다. 이러면 떨어진다. 쿠키와 세션은 비교대상이 아니다.
http 상태를 유지하고 싶다면? 사용자마다 쿠키가 있다.
옛날엔 id pwd를 쿠키에 저장했었다. 쿠키는 내부적으로 브라우저에 저장되어있다. 브라우저에 저장이 되면 물리적으로는 (중요 정보를 클라이언트에 저장하면 안되는데) 폴더에 저장이 되는데, text 파일로 저장이된다. 텍스트 파일은 hello.net@honux.txt와 같이 저장되었다.
이렇게 절대로 하면 안된다. 이렇게 구현하면 id/pwd가 네트워크를 타고 쿠키에 담겨 서버로 간다. 서버는 디비를 뒤져 매칭을해준후에 적절하면 response를 준다. 그 시대에 rdb를 매번 뒤지는데, 말도 안되는 짓이었다.
이렇게 하지 않기 위해, 요새는 다르게 한다.
웹은 상태를 가질 수 없다.
쿠키는 브라우저에 저장되고, 세션은 서버에 저장된다. -> 80 진실과 20 거짓.
http는 무상태 프로토콜이다. 상태를 가질 수 ㅓㅇㅄ다.
요샌 예외가 있는데, 커넥션을 유지하고 싶어서 웹소켓...
웹소켓은 http 위에서 돌아가는 웹프로토콜이 아니다. 웹소켓은 시작은 http로 들어가지만 tcp/ip위에서 돌아가는데, 이러면 성능이 좋아진다. 웹소켓에서 동영상 전송하는 프로토콜은 ..?
http와 tcp/ip
서버에 장부를 갖고 세션 id 이름과 매치하는지 보는 것이다. 장부를 고객에게 넘기지 않듯이, 클라이언트에게 주요 정보를 넘기면 안된다.
로드밸런서가 서버 앞단에서 사용자 구분해서 패킷을 적당한 곳으로 보내는 스티키 세션. 로드밸런서는 http 헤더를 읽을 수 있어야 패킷을 적당히 보낼수있으니, 7계층을 지원해야한다. 그래서 L7이라고 부른다. 로드밸런서 중에 L4라고 4계층 하는데, 스티키 세션은 지원 못하지만 로드밸린싱은 된다. (L4는 무작위 밸런싱)
set-cookie에 세션 id는 민감한 정보는 안들어있다. session-id를 바꾸면 다른 사용자가 되는 것이다. 그렇지만 우연히 다른 사용자가 되기는 어렵다. 왜냐하면 session-id가 40바이트쯤으로 엄청 크기 때문이다. jwt 토큰 크기가 크다
쿠키와 세션의 차이가 무냐묻냐면 세션은 서버 측에 저장한느 사용자 정보이고 http 헤더로 사용자 정보를 읽어오고..어쩌고...
세션id는 어ㅓㄸㅎ게 만드냐? 무작위로 만들어내고, 귀찮으면 uuid로 만들어낸다. 적당히 긴 랜덤 문자열 만들면 된다. 20바이트면 맞출 확률이 낮다. 디비에서 매칭이 되면 클라이언트로 세션 id만 돌려준다.
http는 stateless라서 다음 요청이 무엇일지 알수없지만, 세션 id로 성공적이라면 정보가 세션 db에 들어있다. 세ㅕㅅㄴdb는 메모리??에 있다. 해시맵으로 구현하면된다. 유효 id에 해당하는 객체 있는지 보고 있으면 돌려주면 된다. 로그아웃 구현은 어떻게 하냐? 로그아웃 url은 post로 많이 한다. 답은 없다.
사용자가 유효한지 아닌지 세션 id가 쿠키에 들어있는데, valid user인지 체크를 하고 (아니면 로그인 페이지로 가거나 401권한없음 잘못된요청)
HttpSession은 서블릿pSession은 서블릿이라 적절하지 않은 사용법인데 공부용으로 쓴다. http붙은애들은 대부분 서블릿 객ㄱ체인데, 현업에서 ㄴ대부분 더 추상화된 springsecurity를 쓰고, 어렵다.
아무튼db에서 valid user인지 확인하면 세션 db에서 delete sessionId하면 된다. 세션db에서 해당 정보를 지우고 응답을 해줘야하는데 사용자 브라우저에서 쿠키를 지워줘야한다. delete cookie이런 api는 없다. 쿠키 유효시간, 만료시간을 지금으로 해주면 된다. 그럼 세션디비에서 브라우저로 전달됐을때 now는 이미 지나있다. 그럼 브라우저에서 쿠키 삭제한다.
클라이언트 쿠키/ 서버 세션 전부 지워야 로그아웃해야한다. 서버만 지우면 다음 로그인때 유효하지 않은 요청이라고 자동으로 풀린다.
세션db엔 일반적으로 만료시간이 있다. 이게 없다면 메모리가 폭발할 것이다. 쿠키값 뒤져서 로그인하는 등 보안상의 문제도 있다. 요새는 로그인 유지시간이 (예전 30분) 2주~1달로 길다.
token을 보낼때 refresh 짧)와 auth(길) 두개를 보내 짧은게 만료되면 긴것으로 로그인한다?????!!
회원가입은 form으로 보내진다. 세션 db남겨놔도
세션정보가 서버의 메모리에 저장되면, 서버가 여러대일 경우 다른 서버와 세션 정보를 나누기 힘들 것 같습니다. 이럴 때 세션 디비를 쓰는것.
L4 세션 디비에 저장하고, REDIS의 장점은 액서스 타임이 마이크로세컨드 단위로 매우 빠르다. Redis는 2세대 방식이다.
1세대 방식은? 세션 서버 redis가 없을 경우에는 어떻게 하냐면, 서로 세션 정보 넘겨주기. 별도의 channel을 만들어 서버끼리 통신할수있게 해 vertix?라고 한다. 빠른건 이게 더 빠르다. 메모리에 들어가기 때문이다. 로그인 하는 순간 나머지 서버에 전부 로그인정보를 전파해주는것이다. 세션 디비는 필요없다.
1)sticky 세션 쓸 떄:
L7
디비에 세션 정보가 별도로 유지된다.
세션 디비(SDB) 필요하지 않다. 사용자별로 1번 서버면 1번서버, 2번 서버면 2번 서버랑만 통신한다. 사용자가 특정서버로 가는 것이 보장되기 때문에 세션디비 필요없고 로드밸런싱 잘 안된다. 개발자는 추가 개발 안해도되어서 좋다.
2) REDIS(SDB)쓰는 경우
L4를 쓴다고 해보자.
세션 정보가 세션 db로 아예 빠진다. 각 사용자가 어떤 서버로 갈 지 모르고 세션디비가 각 디비와 통신을 하고 있다.
이럴때 컨트롤러에서 일 다 못하고 서비스를 분리해야한다. 별도의 세션 디비가 필요하니까. 그런데 스프링에선 추상화가되어있어 session=redis설정만 하면 다 해준다. 아니면 탐캣 설정으로도 세션은 redis라고 설정하면된다.
단점은 sdb가 돈이란 것이다.
3)L4 통신방식
서버 두개 두고 자기들끼리 통신하게 함
특별한 communication channel두고 통신하게 하니까 세션 12가 아니라 세션 자체가
커뮤니케이션 채널 구성 어렵고 메모리 사용 증가한다. 이제 ㅇ ㅣ방법을 사용하는 것이 거의 없다.
이젠 2방식을 많이 쓴다. redis 수명 지정해주면 lru가 만료가 된다.lru least recently used로 한명을 쫓아낼때 디비 사용량보다 사용자가 쫓아내야할 때 강제 로그아웃시켜야하는데, 가장 옛날에 사용한 사용자를 로그아웃시키는 것이다. ..
수명 만료란 것은 1시간 정해두면 1시간 후에 1시간사용자들 일률적으로 로그아웃시킨다.
view 깊게 할 필요가 없다. 나머지는 스태틱에넣어두면 프론트에서 해준다.
메세지 컨버터를 통해서 jackson 방식으로 뱉어준다.
쿠키는 httpservletRequestdp에 들어있울 것. 컨트롤러는 아무거나 담을 수 있다. 매개변수, 리턴 값으로도.
Cookie[] cookies = req.getCookies();
for(Cookie c: cookies) {
c.getName();
c.getValue();
}
return new MyResponse("ok", "I don't know");
8억... 영익 2억..
lru: 운영체제 챕터에 있다
쿠키와 로컬 스토리지.
o auth??