본문 바로가기

Node

Passport 모듈로 회원가입 및 로그인 하기 - Passport 모듈화 적용

 

passport 모듈 설정

// passport 모듈
var passport = require("passport"); // 인증을 위해 필수 모듈
var flash = require("connect-flash"); // 사용자한테 메세지를 전달하는 모듈
//Passport 사용 설정 (반드시 세션설정 밑에 기술)
//Passport 의 두개의 함수를 호출했을 때 반환하는 객체를 미들웨어로 사용
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());

 

router 모듈 설정

var router = express.Router();
app.use("/",router); 

// 모듈화로 빠진 Passport routing부분 호출해오기
var userPassport = require("./router/userPassport");
userPassport(router,passport);

// 모듈화로 빠진 Passport부분 호출해오기
var configPassport = require("./config/passport/passport");
configPassport(app,passport);

 

 

모듈화ⓛ. Route 분리

userPassport.js 

module.exports = function(router,passport) {
	
	console.log("userPassport 호출됨");


	//router1. 홈화면
	router.route("/").get(function(req,res){
		
		res.render("index.ejs");
		
	});

	//router2. 회원가입조회 
	router.route("/signup").get(function(req,res){
		
		res.render("signup.ejs",
				{message:req.flash("loginMessage")});
		
	});

	//router3. 회원가입요청 (결과페이지)
	router.route("/signup")
		.post(passport.authenticate("local-signup",{
		
		successRedirect : "/profile",
		failureRedirect : "/signup",
		failureFlash : true 
		
			}));

  // ~ router7까지. 생략
	
};

 

 

모듈화②. Passport의 serializeUser, deserializeUser 메소드 처리 

사용자 정보를 세션에 넣고 빼는 기능을 하는 두 메소드를 모듈화 시켜본다

 

 

passport.js

로그인 성공/회원가입 성공의 경우에 passport.serializeUser 가 자동 실행되므로 관련 파일 모듈을 가지고 온다.

var localLogin = require("./localLogin");
var localSignup = require("./localSignup");

localLogin.js에서 로그인 성공 시 실행되는 

 done(null, user);

에서 user 객체를 전달받아 passport.serializeUser에 의해 세션에 해당 user값을 저장하는 작업을 한다.

module.exports = function(app,passport){	

	//사용자 인증 성공 시 호출됨
	passport.serializeUser (function(user,done){	
    
		done(null,user); 		
        
	});

	// 사용자 인증 이후 사용자가 요청할 때마다 호출하는 부분
	passport.deserializeUser (function(user,done){
    
		done(null,user); 
		
	});
	
	// 인증 방식 설정을 통해 localLogin, localSignup 불러옴 
	passport.use("local-login",localLogin);
	passport.use("local-signup",localSignup);	
	
	// 이제 다른파일에서는 로그인,회원가입 기능을 이용하기 위해 이 passport만 갖다 쓰면 되는 구조	
}

serializeUser 메서드

 function(user,done) 이용해서 session에 저장할 정보 done(null,user) 같이 두번째 인자로 넘기면 된다. 이 때 user 넘어오는 정보는 앞의 LocalStrategy 객체의 인증함수에서 done(null,user)에 의해 리턴된 값이 넘어온다.

 예제에서는  user 객체 전체를 사용자 session 저장하였다.  - done(null, user) 가 세션에 저장하는 부분

 

deserializeUser 메서드

node.js 모든 페이지에 접근할때마다 deserializeUser가 발생한다. deserializeUser에서는 session 저장된 값을 이용해서, 사용자 Profile 찾은 , HTTP Request에 값을 리턴한다.

deserializeUser callback함수의 첫번째 인자로 넘어오는 내용”user”는 세션에 저장된 사용자 정보이다.  예제에서는 session에 해당 사용자의 정보를 저장하였기 때문에 별도의 변경없이 done(null,user)를 이용해서 그대로 session에서 읽은 내용을 리턴하는 것이다.

이렇게 리턴된 내용은 HTTP Request  “req.user” 값으로 다른 페이지에 전달된다.

 

 

 

passport.use의 의미?

use(이름,인증방식객체) : 이름은 단순히 함수끼리 구별하기 위한 용도 (사용자 정의임)

 

 

모듈화③. Passport Strategy 분리 (인증방식객체 분리)

= 인증 방식 객체인 localSignup.js, localLogin.js을 분리한다

 

인증방식객체 1. Passport 로그인 설정 (localSignup.js)

 

app3.js에서 Local Strategy를 사용하기 위해서 모듈을 불러 들인다

var LocalStrategy = require("passport-local").Strategy;

 Local Strategy에 의해서 인증 시에 호출되는 인증 메소드를 정의한다

module.exports = new LocalStrategy ({	
	
	usernameField : "email",
	passwordField : "pwd",
	
	// 아래 콜백함수의 첫번째 파라미터로 req객체가 전달됨
	passReqToCallback : true
	
	}, function(req,email,pwd,done) {
	
		console.log("passport의 local-login 호출");
		console.log(email + ":" + pwd);
		
		// 데이터베이스 객체 생성
		// 모듈화됐으니깐 app.get => req.app.get 
		var database = req.app.get("database");
		
		database.UserModel
		.findOne({"email":email}, function(err,user){
			
			//조회하다가 에러 발생한 경우
			if(err) {return done(err);} // 원래는 throw err; 이렇게 처리했음
			
			// 1. 조회는 했는데 해당 이메일로 등록된 사용자가 없는 경우
			if(!user) {
				console.log("이메일이 일치하지 않음");
				
				//검증 콜백에서 두번째 파라미터를 false로 해서 인증 실패한것으로 처리
			
				return done(null,false,
						req.flash("loginMessage","등록된 계정이 없습니다")); // flash : 메세지 넘겨주는 애 
			}
			
			
			// 2. 조회 했고 해당 이메일로 등록된 사용자를 찾은 경우
			
			// 2-1.  비밀번호 비교
			var authenticated =
				user.authenticate(pwd,
						user._doc.salt,user._doc.hashed_pwd);
			
			if(!authenticated) {
				
				console.log("비밀번호가 일치하지 않음");
				
				return done(null,false,
						req.flash("loginMessage","비밀번호가 일치하지 않음")); 
			}
			
			// 2-2. 비밀번호까지 전부 일치한 경우
			console.log("계정과 비밀번호가 일치함");
			
			return done(null,user);
			
		});
	
});

(참고) Passport의 LocalStrategy 는 디폴트로, username이라는 필드와 password라는 필드로 각각 로그인 id와 비밀번호를 받도록 되어 있는데 ,이 예제에서만 username 대신 앞의 폼에서 정의한 email을 받도록 변경한 것이다

 

 

인증방식객체 2. Passport 회원가입 설정 (localLogin.js)

var LocalStrategy = require("passport-local").Strategy;

module.exports = new LocalStrategy ({	
	
	usernameField : "email",
	passwordField : "pwd",
	
	// 아래 콜백함수의 첫번째 파라미터로 req객체가 전달됨
	passReqToCallback : true
	
	}, function(req,email,pwd,done) {
		
		// 사용자가 입력한 name, pwd를 받는다 
		var paramName = req.body.name || req.query.name;
	
		console.log("passport의 local-signup 호출");
		console.log(email + ":" + pwd);
		
		process.nextTick(function(){
			
			// 데이터베이스 객체 생성
			var database = req.app.get("database");
			database.UserModel
			.findOne({"email":email}, function(err,user){
				
				//조회하다가 에러 발생한 경우
				if(err) {return done(err);} // 원래는 throw err; 이렇게 처리했음
				
				// 1. 이미 등록된 사용자가 있는경우 
				if(user) {
					console.log("이미 이메일 계정이 있습니다");
					
					//검증 콜백에서 두번째 파라미터를 false로 해서 인증 실패한것으로 처리				
					return done(null,false,
							req.flash("loginMessage","이미 이메일 계정이 있습니다")); // flash : 메세지 넘겨주는 애 
				} else {
				
				// 2. 등록된 사용자가 없는 경우	
					console.log("등록된 사용자가 없으므로 회원가입 진행");
										
					var user = 
						new database
						.UserModel({"email":email,
							"pwd":pwd,
							"name":paramName});
					
					user.save(function(err){
					
						if(err) {throw err;} // 북마크 - 여기서 에러남
						
						console.log("사용자 데이터 추가 완료");
						
						return done(null,user); // user만 넘김
					});
					
				} // end...if
		}); // findOne 끝
		
		}); // nextTick 끝	
	
});