3부: 로그인 및 세션 모델
여기까지입니다, 파트 0 그리고 1부 애플리케이션에 사용된 데이터 모델과 사용자 문서를 다룬 다음 파트 2 노드메일러와 센드그리드를 사용하여 이메일을 통해 계정을 인증합니다. 이는 모든 소셜 미디어 웹사이트에서 사용자를 시작하는 데 있어 핵심적인 부분이지만, 이제 사용자가 로그인하여 소셜 네트워크의 콘텐츠에 액세스할 수 있는지 확인해야 합니다. 이제 시작하겠습니다!
필요한 자료:
- Node.js
- Express
사용된 노드 모듈:
- N1QL이 포함된 Couchbase Node.js SDK
- 본문 파서
- uuid
먼저 사용자를 인증해야 합니다. 이를 위한 API 엔드포인트는 '/api/loginAuth'.
'/api/loginAuth' API
인증은 이메일과 비밀번호가 모두 백엔드에 제대로 전달되었는지 확인하는 것으로 시작됩니다. 누락된 경우 오류가 반환됩니다. 이 API의 현재 구현에서 오류는 프론트엔드에 Angular.js, ng-messages 오류와 함께 표시됩니다. 또한 사용자 이름과 비밀번호를 POST 요청을 통해 이 엔드포인트로 전송합니다. 이렇게 하면 URL이 비밀 정보를 노출하지 않으므로 GET보다 보안이 한층 강화됩니다. 물론 애플리케이션을 올바르게 배포하려면 중간자 공격을 피하기 위해 HTTPS를 포함해야 합니다.
첫 번째 유효성 검사 후 'User.advancedSearch' 함수를 실행하여 사용자가 검색 중인 이메일 주소의 문서를 찾습니다. 이 함수는 사용자가 가지고 있는 정확한 이메일 주소의 결과 하나를 반환하는 것이 이상적입니다. 보시다시피, loginAuth API의 첫 번째 코드 스니펫입니다, 'if (x.length === 0)'를 호출하여 이메일 주소가 등록되었는지 확인하고 등록되지 않은 경우 오류를 발생시킵니다. 둘째, 사용자 이름과 비밀번호 조합이 유효한지 확인합니다. 'User.validatePassword' 함수를 사용하여 사용자가 입력한 비밀번호의 해시 버전이 사용자 문서에 저장된 해시 버전과 일치하는지 확인합니다. 여기에는 생성한 원본 사용자 문서에서 사용한 것과 동일한 해시 함수가 사용됩니다. 'User.create' 함수입니다.
User.validatePassword 함수
다음으로 사용자의 이메일이 인증되었는지 확인합니다. 이 과정이 어떻게 진행되는지 잘 모르겠다면 다음을 참조하세요. 파트 2 를 살펴보았습니다. 요약하면, 사용자가 실제로 이메일을 인증한 경우 변경되는 'login.emailVerified' 속성이 있습니다. 이 속성은 부울 속성이므로 'true'로 평가되는지 확인하고, 그렇지 않은 경우 사용자에게 이메일이 아직 확인되지 않았음을 알리는 오류 메시지를 던집니다.
마지막으로 위의 모든 조건이 충족되면 실제로 사용자를 로그인하는 과정으로 넘어갑니다. 여기에는 올바른 사용자 문서에 있는 'timeTracker.loginTimes' 배열에 현재 시간을 추가하는 작업이 포함됩니다. 이 작업은 User.addLoginTime 함수에 있는 models/usermodel.js.
User.addLoginTime 함수
이 함수는 N1QL 쿼리를 사용하여 사용자의 배열을 가져와 기본적으로 동일한 배열로 설정하지만, 'timeTracker.loginTimes' 배열에 현재 시간을 추가합니다. 현재 N1QL을 사용하여 기존 배열에 무언가를 추가할 수 있는 방법이 없으므로 해당 기능이 추가될 때까지 사용할 수 있는 임시방편입니다. 이 경우 업데이트 문을 사용하면 검색하려는 키가 이미 존재하며 기존 배열만 업데이트하고 있는지 확인할 수 있습니다.
참고: 항상 사용 키 절을 사용하여 특정 문서 ID를 검색할 수 있습니다. 사용 'WHERE META(버킷명).id=var' 또는 기타 어디 문은 초고속 K-V 인터페이스를 사용하지 않으므로 변경 사항과 일치하지 않을 수 있습니다. 이 예제에서는 사용 키 를 사용하여 속도를 높이고 쿼리에 사용할 모든 새 변수를 배열로 Node.js SDK에 전달합니다. 이렇게 하면 쿼리가 더 안전해지며 SQL 인젝션과 유사한 N1QL 인젝션을 피할 수 있습니다. 쿼리에서 배열의 이러한 요소가 배치될 위치는 '$'로 표시됩니다. '$' sybmol과 함께 지정된 정수는 배열의 어떤 요소를 사용할지 지정합니다. 이에 대한 인덱싱은 1부터 시작됩니다.
실행에 성공하면 다음 단계로 돌아갈 수 있습니다. routes/routes.js 를 API 엔드포인트에 연결하고 'Session.create' 함수를 호출합니다. 이제 보다 안전한 애플리케이션을 만들기 위한 시작 단계에 도달했습니다. 사용 'Session.create'를 호출하면 지난번 함수에서와 마찬가지로 사용자 ID를 전달합니다. 이는 다음에서 찾을 수 있습니다. models/sessionmodel.js.
Session.create 함수
이 함수는 사용자 ID를 가져와서 고유 식별자인 세션ID와 연결된 사용자의 사용자 ID가 있는 세션 문서를 생성하여 식별할 수 있도록 합니다. 'userID' 필드는 '내 프로필' 페이지를 만들거나 소셜 네트워크에서 특정 게시물을 작성한 사용자를 식별하고자 할 때 유용합니다. 이 문서를 추가하기 위해 간단한 Couchbase SDK 삽입물을 사용합니다. 그런 다음 문서에 만료를 추가하여 문서가 추가된 후 1시간(3600밀리초) 후에 만료되도록 합니다. 사용자가 한 시간 이상 로그인한 후에는 다시 로그인해야 합니다. 여기서 개선할 수 있는 한 가지 방법은 터치() 함수를 사용하여 사용 중 세션을 확장할 수 있습니다. 이 문서가 생성되면 세션 모델과 함께 콜백을 보내고, 세션 모델에서 routes/routes.js 파일에 세션ID와 만료가 포함된 객체를 프런트엔드로 전송합니다. 이 세션ID는 브라우저의 로컬 스토리지에 저장되어 필요할 때마다 액세스할 수 있습니다.
세션ID가 localStorage에 추가되면 보호된 경로에 대한 HTTP 요청 헤더에 세션ID를 함께 보냅니다. 보호된 경로는 현재 로그인한 사용자만 액세스해야 하는 보안 정보가 있는 모든 API 엔드포인트입니다. 이 프로젝트에서는 Angular.js를 사용했기 때문에 각 API 요청의 $http 헤더에 localStorage의 세션ID를 넣었습니다. '$scope.getAllUsers' 함수입니다.
$scope.getAllUsers 프런트엔드 함수
그리고 '/api/advancedSearch' 는 보호되는 경로의 한 예이며 위의 '$scope.getAllUsers' 함수를 호출합니다. 코드에서 '/api/advancedSearch' 엔드포인트를 호출하는 것을 볼 수 있습니다. 'Session.auth'를 호출한 다음 함수 인수의 콜백을 호출합니다.
'/api/advancedSearch' API
그리고 'Session.auth' 함수의 models/sessionmodel.js 는 요청 헤더에서 세션ID를 가져오는데, $http 헤더에서 분할 연산을 수행하여 구문 분석합니다. 세션ID는 사진 업로드와 같이 요청 본문 인스턴스에 있을 수 있으므로, 이는 'Session.auth' 함수도 사용할 수 있습니다. 헤더 또는 요청의 다른 부분에서 세션ID를 가져온 다음 N1QL 쿼리를 수행하여 세션 문서를 찾습니다. 다시 한 번, '사용 키' 는 속도를 염두에 두고 사용됩니다. 전달한 세션ID로 문서를 찾을 수 없는 경우(대부분 1시간이 지나 만료되었음을 의미) 객체와 함께 응답이 전송됩니다. 이는 프런트엔드에서 다양한 방식으로 처리할 수 있으며, 제 구현에서는 사용자를 로그인 페이지로 되돌려 보내기만 하면 됩니다. if ('!currentSession').
Session.auth 함수
이 세션 기반 보안은 모든 액세스 제어가 백엔드에서 확인되므로 웹사이트의 보안을 유지합니다. 쿠키가 만료되면 사용자가 로그아웃되는 단순 쿠키와 달리 개발자가 로그인을 완전히 제어할 수 있습니다. 만료 쿠키를 사용하면 프런트엔드 자바스크립트를 쉽게 삭제하거나 변경하여 사이트 정보에 액세스할 수 있습니다. 만료 쿠키를 사용하는 이유는 '/api/loginAuth' 또한 세션 문서에서 프런트엔드로 만료 정보를 전달하는 것은 다른 개발자가 원하는 경우 프런트엔드에 만료 쿠키를 추가할 수 있도록 하기 위함입니다.
만약 'Session.auth' 함수가 성공하고 올바른 문서를 찾으면 문서의 사용자 ID를 요청 객체로 전달하며, API 엔드포인트의 다른 함수가 이 함수에 액세스하여 '내 프로필'과 같은 사용자별 정보를 받거나 게시글에 대한 사용자 ID를 문서에 저장할 수 있습니다.
이것으로 터치베이스에 대한 네 번째 튜토리얼을 마쳤으며, 애플리케이션을 안전하게 유지하는 한 가지 방법을 이해하는 데 도움이 되었기를 바랍니다. JSON 웹 토큰이나 OAuth 2.0과 같은 다른 대안도 있지만, 이 경우에는 세션 기반 접근 방식을 선택했으며 이 사용자 인증 방법을 이해하는 데 도움이 되었기를 바랍니다. 질문, 의견 또는 피드백이 있으시면 아래에 댓글을 남겨 주세요.