본문 바로가기

프로그래밍/Node.js

[Do it! Node.js 프로그래밍] 10일차

1. 공부한 범위


[09] 패스포트로 사용자 인증하기



2. 공부한 내용


[09] 패스포트로 사용자 인증하기

09-1 패스포트로 로그인하기 

- 패스포트는 노드에서 사용할 수 있는 사용자 인증 모듈이다. 해당 모듈은 사용 방법이 간단할 뿐 아니라 인증 기능을 독립된 모듈 안에서 진행할 수도 있도록 돕는다.

- 패스포트가 제공하는 수백 가지의 인증 방식 중 어떤 방식을 사용할 것인지 결정하는 것이 스트레티지다.

- 대표적인 인증 방식으로는 DB에 저장된 사용자 정보와 비교하는 로컬 인증 방식(Local Strategy), 페이스북이나 트위터의 계정을 사용하는 OAuth 인증 방식등이 있다.

- 패스포트 미들웨어를 통해 사용자를 인증할 때 미리 설정해 둔 인증 방식으로 사용자를 인식하는 데 성공하면 해당 정보를 세션에 저장하게 된다. 해당 세션 정보는 사용자 인증에 성공했을 때만 사용할 수 있기 때문에 로그인 이후의 요청 정보를 처리할 때 이 정보를 통해 사용자 인증 여부를 구분할 수 있다.

 

패스포트의 기본 사용 방법 알아보기

- 인증에는 보통 복잡한 과정을 거치지만, 패스포트를 사용하면 해당 과정이 상당히 단축된다.

 

- 패스포트를 통해 인증을 할 때는 위 코드와 같은 방식을 자주 사용하게 된다.

- 라우터 객체에 라우팅 함수를 등록하는 코드 방식이다.

- 클라이언트에서 보낸 인증 정보로 인증하고자 한다면 passport.authenticate() 메소드를 호출하며 동시에 어떤 스트레티지를 사용할 지 지정해야 한다.

 

- 이 코드는 로컬 인증 방식을 사용한다는 것을 의미한다.

- 보통 인증에 성공했을 때는 "/"인 홈으로, 실패했을 때는 "/login"인 로그인 페이지로 리다이렉트되도록 만든다.

 

플래시 메시지와 커스텀 콜백 이해하기

- 리다이렉트를 사용해 응답을 전송할 때는 보통 플래시 메시지를 같이 사용한다.

- 플래시 메시지를 사용하고자 할 때는 connect-flach 외장 모듈을 이용해야 한다.

- 플래시 메시지를 사용하는 방법은 간단하다. 요청 객체의 flash() 메소드를 사용할 때 파라미터가 두 개면 플래시 메시지를 설정하는 것, 파라미터가 하나면 플래시 메시지를 조회하는 것이다.

ex) request.flash("loginMessage", "등록된 계정이 없습니다.");

ex) request.flash("loginMessage");

- passport.authentication() 메소드를 호출할 때 failureFlash 옵션을 넣을 수 있다. 이렇게 만든다면 코드에서 명시적으로 flash() 메소드를 호출하는 것이 아니라 패스포트 모듈이 자동으로 해당 메소드를 호추하며 오류 메시지를 설정하게 된다.

- 오류 메시지는 스트레티지를 설정할 때 검증 콜백(Verify Callback)이 설정되어 있다면 자동으로 설정되게 된다.

- 검증 콜백 : 인증을 처리하는 함수, 어떤 문제로 인증이 실패했는지 정확하게 알려준다.

 

- 위 방식처럼 플래시 메시지를 직접 설정해 웹 문서로 전달하는 방식도 사용이 가능하다.

- 만일 기본적으로 제공되는 기능들로 원하는 결과물을 도출해낼 수 없다면 커스텀 콜백을 사용해 사용자 인증을 수행할 수도 있다.

 

- 커스텀 콜백을 활용한 예로서 이 방식으로 코드를 구성할 경우 클로저를 통해 request, response 객체에 접근이 가능해진다.

- 일반적으로는 세션을 유지하고자 하기 때문에 위같은 코드는 자주 사용되지 않는다.

 

스트레티지 설정과 검증 콜백

- 스트레티지는 인증 방식을 경정하며, 사용자 아이디와 비밀번호를 사용하는 로컬 인증 방식 뿐 아니라 OAuth나 OpenID와 같은 인증 방식까지 지원할 수 있도록 각 인증 방식이 정의되어 있다.

- 클라이언트 요청을 인증하고자 한다면 스트래티지가 반드시 먼저 설정되어 있어야 하며 user() 함수를 통해 가능하다.

- 로컬 인증 방식을 사용하기 위해서는 passport-local 모듈을 먼저 설치해야 하며 LocalStrategy 객체를 사용하는 전형적인 코드는 아래와 같다.

- 스트레티지를 설정할 때는 검증 콜백에서 인증 결과를 처리하게 된다. 위 코드에서는 인증 결과를 처리하는 콜백 함수가 이것이다.

- 검증 콜백의 목적은 인증 정보들을 가지고 있는 사용자를 찾는 것이다. 해당 결과는 done() 메소드를 통해 클라이언트에게 되돌려준다.

 

09-2 로컬 인증하기

 

로컬 인증을 위해 데이터베이스 스키마와 패스포트 설정하기

- 패스포트를 초기화하고자 한다면 passport.initialize() 미들웨어가, 로그인 세션을 유지하고자 한다면 passport.session() 미들웨어가 필요하다.

 

- 스트레티지를 설정하는 과정에서 이름을 local-login으로 설정했기 때문에 후에 authenticate() 메소드를 호출할 때도 이 이름을 사용해야 제대로 인식된다.

- 첫 번째 파라미터에는 local-login을 입력해 인증 처리를 위해 등록한 함수를 해당 이름으로 인식할 수 있도록 만든다.

- 두 번째 파라미터로 전달되는 콜백 함수가 호출되면 DB에 저장된 email과 password 칼럼을 비교해 인증 결과를 알려준다.

 

- 이 구조는 local-login과 거의 유사한 구조를 가지며 또한 페이스북이나 구글 등을 이용한 사용자 인증 방식에서도 똑같이 사용되기 때문에 코드를 재사용하기에 제한이 적다.

 

- 사용자 정보를 저장(Serialize) 및 복원(Deserialize)하는 코드로 요청이 있을 때마다 인증 내역을 다시 불러와준다.

- 이 부분이 필요한 이유는 세션 저장과 복원이 패스포트 모듈이 아닌 다른 코드에서 처리하도록 되어있기 때문이다.

 

로그인과 회원가입 화면을 만들기 위한 라우팅 함수 등록하기

 

- 위 그림은 로그인과 회원 가입을 위해 필요한 뷰와 라우팅 함수들이다.

 

- 라우팅 함수를 통해 ejs파일을 렌더링하며 로그인 시 패스포트에 등록된 코드를 실행해 결과를 반환한다.

- get과 post로 login을 요청받을 때의 결과를 작성했다.

- get 방식으로 요청할 때는 단순히 뷰 템플릿을 출력한다.

- post 방식으로 요청할 때는 패스포트의 authenticate() 메소드를 통해 사용자 인증을 처리한다.

- 로그인에 성공했으면 사용자 정보를 표시하는 /profile 경로로, 실패했으면 재로그인을 위해 /login으로 이동한다.

 

- 회원가입 절차를 처리하기 위한 코드

 

- 사용자 프로필 정보를 보여주기 위한 라우팅 함수다.

- 사용자 인증이 성공했는지 판단하는 방법으로 req.user 객체를 확인하는 방식 말고도 req.isAuthenticated() 메소드를 호출하는 방식도 있다.

 

- 로그아웃을 위한 코드

 

로그인과 회원가입 화면을 만들기 위한 뷰 템플릿 만들기

- 뷰 템플릿을 만들기 위해 부트스트랩을 사용해 구성한다.

- 부트스트랩은 모던한 느낌의 화면 스타일을 쉽게 만들 수 있는 UI 라이브러리다.

 

- 부트스트랩에 대한 추가적인 정보를 얻을 수 있는 사이트

 

- 부트스트랩을 활용해 만든 로그인 뷰 템플릿

 

 

 

- 회원가입 코드와 프로필 화면 코드

 

09-3 패스포트 관련 코드를 모듈화하기

 

- 모듈화를 수행한 결과는 위 그림과 같이 분리가 된다.

- 사용자 인증을 config/passport.js로 분리했다.

- module.exports로 할당된 함수 안에는 app.js 파일에 들어 있던 코드가 일부 들어 있다. 그렇기 때문에 app 객체나 passport 객체를 참조해야 할 때가 생긴다. 두 객체를 파라미터로 전달받는 익명함수를 만들면 모듈화가 쉽게 가능해진다.



 

- app.js에 있던 모든 인증 과정을 모듈화한 결과

- app에는 require를 통해 해당 코드들을 불러와야 정상적으로 작동하게 된다.





 

- 패스포트를 통한 인증이 성공해 사용자 프로필 정보를 출력하게 된다.