프로그래밍/서버, DBMS

[서버] 웹 서비스 단일 로그인 (아이디당 1세션 유지)

포도알77 2019. 3. 10. 15:52
 대부분의 웹 서비스 프레임워크에서 세션을 관리하는 기능을 제공한다.  

 이런 세션 기능들은 1번 로그인을 하면, 브라우저내의 어떤 탭에서도 로그인이 유지된다. 하지만 일부 프로젝트는 반드시 1계정 1세션 유지가 정책이 되어야 하는 경우도 있다.  



 [세션의 정의와 세션 관리 기능이 동작하는 방법] 

 어떤 프레임워크를 사용하든지, 세션은 서버 기준의 1개의 일시적인 연결이다. 즉, 어떤 클라이언트가 접근하였을때 세션 ID를 만들고, 로그인시 클라이언트의 정보를 해당 세션 ID(Key)에 대한 값(Value)로 저장한다.


 그리고 마지막으로 클라이언트 브라우저에게 해당 세션 ID(세션 ID, 세션 Key를 혼용하겠음)를  전달해주면서, 해당 세션키를 이후 모든 연결에 전달하라고 요구한다. 이 경우 브라우저는 이 세션키를 쿠키에 저장하게 된다. (따라서 모든 탭에서 접근이 가능하다.==로그인 상태가 유지되어있다.)   


 따라서 1 계정 1 세션을 위해서는 세션값이 아닌 새로운 임의문자열을 로그인시마다 생성하여, 클라이언트에게 전달해야한다. 이 임의문자열을 UID라고 정의하고 계속 글을 이어간다.




 방법1) 

 우선 가장 간단한 방법은 계정 ID를 Key로하여, Value에 세션 ID와 UID을 매칭하여 저장한다음, 동일하게 클라이언트 브라우저에게 전달한다. 그리고 해당 계정이 다른 브라우저에서 로그인하였을때, 이 값(세션과 UID)과 비교하여 현재 계정이 사용중인 세션을 저장한다. 

 이렇게 세션키를 저장하면 서버는 항상 새로운 세션키 값을 저장할 수 있고, UID를 바탕으로 사용자는 항상 마지막 로그인이 발생한 세션에서만 로그인이 유지된다.  


 하지만 방법1은 틀렸다. 따라서 1 계정 1로그인 정책을 설정하기 위해서는 UID를 브라우저에 저장하는 방법(Set cookie)이 아닌, 한 탭에서만 관리되는 곳에 저장해야한다. (쿠키는 브라우저의 모든 탭에서 공유된다. 세션 스토리지, 로컬 스토리지도 마찬가지다)  


 그렇다면 탭마다 관리되는 메모리 영역은 무엇일까? 바로 HTML과 JS영역이다. 즉 서버와 통신할때, 이제부터는 항상 HTML 또는 JS 영역에서 UID 값을 읽고 이를 포함하여 전달해야한다.




 
 방법2) 

 Sync 방식에서는 페이지가 전환되어 버리므로, 이전 HTML, JS영역이 메모리상에서 제거된다. 따라서 서버에 Query 스트링으로 전달하면서, 서버가 이를 다시 릴레이해줘야한다.

 [ex] 
       (1) GET /index?uid=abcd -----> 
       (2) 서버 uid 확인 -----> 
       (3) index내의 html 태그에 uid를 포함하여 클라이언트에게 전달. 

 Async 방식에서는 페이지 전환이 없으므로, 지속적으로 html 또는 js영역에서 이를 관리하면된다.  



(요약)

 (1) 1 계정 1 세션은 기본적인 프레임워크 세션 관리 기능만으로는 불가능하다.
 (2) 브라우저의 탭은 동일한 세션 아이디를 가지므로, 동일 계정이 로그인하는 경우 이를 공유한다. 
 (3) 각 세션을 서버가 구분하기 위해서는 고유 ID를 부여하여야 한다.
 (4) 각 로그인별 고유 ID를 발급하고, 이를 클라이언트에게 전달한 다음 이 값으로 가장 최근 세션을 찾는다.
 (5) 이를 쿠키, 세션스토리지, 로컬스토리지에 저장하면, 이 또한 공유하므로 의미가 없다.
 (6) 탭별 고유 메모리 영역인 HTML, JS에 저장하자.  


 추신) Ajax의 경우에는 sendBefore, complete 이벤트 리스너를 통하여 UID를 전달할 수 있다.
$.ajaxSetup({
  beforeSend: function (xhr){
     // 모든 AJAX를 보내기전에 헤더에 UID를 포함한다.
     xhr.setRequestHeader('uid', $('.uid').text());
  },
  complete: function(xhr){
  }
});
   


페이스북으로 공유카카오톡으로 공유카카오스토리로 공유트위터로 공유URL 복사