request의 메모리 공간에는 scope가 있다.
요청 시에 생성되었다가 응답하면 사라진다.
마치 stack처럼 자동으로 메모리 관리가 된다.
하지만 실제로는 heap에 저장된다!
연결된 버퍼가 연결이 지속되어 있다고 무조건 stateful이 아니라
연결은 끊겨도 서버가 클라이언트를 기억할 수 있다면
stateful이라고 할 수 있다.
http 프로토콜은 기본적으로 stateless 상태이다.
응답을 해주고 나면 전혀 기억하지 않는다.
이런 것 때문에 세션이라는 메모리 영역이 필요하다.
모든 서버는 세션을 가지고 있다.
세션은 heap영역이다.
heap의 어느 부분을 논리적으로 세션이라고 부른다.
세션은 request와 다르게 계속해서
기억하고 있는 메모리 공간이다.
세션은 서버가 종료될 때까지 메모리에 떠있는다.
나는 클라이언트가 요청이 왔을 때 세션에 request를
옮겨주기만 하면 된다.
스트림이 연결되어 있지는 않지만
이것도 stateful하다고 한다!
클라이언트가 최초에 요청할때
인증을 위한 username과 password를 같이 보낸다.
서버 소켓은 받은 username과 password가 DB에 있나 확인 후
있으면 특정 메모리 공간에 해시로 만들어진 키 값(난수)과 홍길동의 이름을 저장해둔 뒤
홍길동에게 키 값을 돌려준다.
그리고 응답이 끝났으니 스트림은 끊기게 된다.
이후에 홍길동이 다시 서버에 접근할 때
서버는 홍길동을 완전 새로운 클라이언트로 인식하지만
숫자만 보냈을 때 저장소에 같은 숫자가 있는지 확인하라는 프로토콜만 존재한다면 인증이 가능하다.
왜냐면 키 값은 해시 난수라서 아무나 알 수 있는 숫자가 아니기 때문이다.
이 키 값은 연결되어 있지는 않지만
연결되어 있는 것처럼 stateful 하게 사용할 수 있다.
이때 서버가 키값과 이름을 저장해놓은 공간을 세션이라고 하고,
클라이언트가 키 값을 저장해놓은 공간을 쿠키라고 한다.
여러 명의 클라이언트가 요청이 들어오면
하나의 세션 공간에 이 사람들의 키 값을 같이 저장한다.
하나의 세션 영역을 공유하는 저장소인 것이다.
내 키값을 지우고 싶으면?
세션을 모두 날릴까? 아니다.
서버 쪽 세션에 있는 쿠키를 삭제한다.
이 행위가 로그아웃이다.
클라이언트가 가진 쿠키를 강제로 삭제한다?
이것도 로그아웃이다.
웹페이지에서 30분 동안 아무것도 안 하면
로그인을 다시 하라고 요청한다.
내 키값이 날아간 것이다.
디폴트가 30분이다.
yml 파일에서 직접 설정 가능하다.
혹은 열려있던 모든 브라우저 창이 닫히면 세션은 유지되지만
클라이언트의 쿠키가 삭제된다.
다시 브라우저를 열어서 페이지로 들어가면
로그인을 요청할 것이다.
최초에 페이지에 방문한 사람에게 JSESSIONID를 준다.
request를 통해 session영역에 접근이 가능하다.
request.getSession( ) 메서드를 사용하면 된다.
클라이언트가 쿠키에 JSESSION 85를 가지고 오면
세션 영역 안에 만들어진
85번 클라이언트의 세션 공간을 가리키게 된다.
세션 공간에 85라는 숫자가 있으면 인증됨이라는 문구를
세션 영역의 85번 공간에 띄우자.
앞으로 인증됨이라는 글자가 있으면
stateful 하게 사용 가능!!
세션은 scope가 길어서 데이터가 사라지지 않는다.
request보다 오랫동안 떠있는 메모리 영역이 필요했던 것이다.
그렇다고 request를 안 쓸 수는 없다.
request는 scope가 짧지만,
메모리 공간을 사용하는 효율이 엄청나다!
클라이언트를 길게 기억하기 위해서 세션에 옮겨두는 것이다.
// 로그인 SELECT * FROM user WHERE username=? AND password=? -> 이런 메서드는 없으니까 직접 만들어!
// 원래 SELECT는 무조건 GET요청
// 근데 로그인만 예외! POST요청
// 이유 : 주소에 패스워드를 남길 수 없으니까!! 보안을 위해!!
// 로그인 - 인증(로그인) X
@PostMapping("/login")
public String login(HttpServletRequest request, User user) {
HttpSession session = request.getSession(); // 쿠키에 JSESSIONID를 85로 가져오면 session의 자기 공간을 가리킴
// 1. DB연결해서 username, password 있는지 확인
User userEntity = userRepository.mLogin(user.getUsername(), user.getPassword());
// 2. 있으면 session 영역에 인증됨이라고 메시지 하나 넣어두자
if (userEntity == null) {
System.out.println("아이디 혹은 패스워드가 틀렸습니다.");
} else {
System.out.println("로그인 되었습니다.");
// 세션에 옮겨담자, request는 사라졌지만 세션영역에 보관
session.setAttribute("principal", userEntity); // principal 인증된 주체 -> 로그인
}
return "redirect:/";
}
인증됨이라고 적혀있는 것보다는
그 사람의 구체적인 정보가 적혀있어야
권한 처리가 가능하다.
mustache 문법( {{ }} )을 쓰면 request를 바로 사용 가능했던 것처럼
세션도 바로 사용이 가능하다.
세션에 user의 구체적인 정보를 저장하기 위해
session.setAttribute( )를 사용한다.
키 pricipal 값 userEntity
principal이라는 키 값으로 해당 클라이언트의
정보가 담긴 userEntity에 접근하는 것이다.
[출처]
https://cafe.naver.com/metacoding
메타 코딩 유튜브
https://www.youtube.com/c/%EB%A9%94%ED%83%80%EC%BD%94%EB%94%A9