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 끝
});
'Node' 카테고리의 다른 글
[드림코딩 앨리 강좌] 타입스크립트 + OOP 마스터 과정 - Chap 4. 객체지향 프로그래밍 (0) | 2022.03.29 |
---|---|
Node.js - Socket.IO 모듈을 이용한 채팅 프로그램 (0) | 2019.11.12 |
Passport 모듈로 회원가입 및 로그인 하기 (모듈화 적용 X) (1) | 2019.11.11 |
Node.js 에 View Template 적용하기 (1) - Semantic UI (미완) (0) | 2019.11.08 |
Node.js + Oracle 을 이용한 로그인/패스워드 웹서버 구축하기 (0) | 2019.11.07 |