안녕세계

[Node.js] passport & passport-local (with Redis) 본문

[Node.js] passport & passport-local (with Redis)

Junhong Kim 2016. 10. 24. 10:06
728x90
반응형

- passport & passport-local -

(with Redis)



지난 post에서는 ElastiCache for Redis를 알아보았는데요.

오늘은 사용자 로그인 인증(auth) 기능을 추가해보겠습니다.

인증이 된 순간에 Redis store에 passport session이 저장 됩니다!


로컬 인증을 하기 위해서는 passport 모듈과 passport-local 모듈이 필요합니다.

기본적으로 node 모듈에 포함 되어있는데 혹시 모듈이 설치되어 있지 않은 경우 아래 두 모듈을 설치해줍니다.


npm install passport

npm install passport-local




[Step 1] 인증 URL 구성


URL 구성은 보통 인증(auth)은 인증끼리 묶어서 관리합니다.

우리는 local login 인증을 할 예정이므로 /auth/local/login 이라는 URL을 만들어줍니다!

auth.localLogin에서는 인증 과정을 진행한 후 JavaScript 체이닝 기능을 통해 결과가 auth.localLoginResult로 나오도록 할 것입니다.


[routes.js]

router.post('/auth/local/login', auth.localLogin, auth.localLoginResult);





[ Step 2] Auth API 작성


글 읽기 귀찮은 분들을 위해 full code 먼저 첨부합니다 -_<

var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var models = require('../models');
var db = require('../util/db');
const User = models.User;

// Local Strategy
passport.use(new LocalStrategy({
usernameField: 'deviceNumber',
passwordField: 'password'
},
function(deviceNumber, password, done) {
var condition = {
deviceNumber: deviceNumber
};

db.findOne(User, condition)
.then(function(user) {
if(!user) {
return done(null, false)
}
return done(null, user);
})
.catch(function(err) {
done(err, null);
});
}));

// Save session to Redis
passport.serializeUser(function(user, done) {
done(null, user.deviceNumber);
});

// Load session from Redis
passport.deserializeUser(function(deviceNumber, done) {
var condition = {
deviceNumber: deviceNumber
};

db.findOne(User, condition)
.then(function(user) {
done(null, user);
})
.catch(function(err) {
done(err);
});
});

module.exports.localLogin = function(req, res, next) {
console.log('in func');
passport.authenticate('local', function(err, user) {
console.log('after auth');
// Local login error
if (err)
return next(err);
// Local login fail
if (!user) {
return res.status(401).send({
code: 0,
message: '로컬 로그인 실패'
});
}
// Local login success
req.login(user, function (err) {
if (err)
return next(err);
// to next function
next();
});
})(req, res, next);
};

module.exports.localLoginResult = function(req, res){
res.send({
code: 1,
message: '로컬 로그인 성공'
});
};

passport 모듈과 passport-local 모듈의 Strategy 를 가져옵니다.

(자세한 내용: http://passportjs.org/docs/authenticate)


* 코드 진행순서

localLogin -> LocalStrategy -> serializeUser -> deserializeUser -> localLoginResult


localLogin에서 passport.authenticate('local', ~) 이 부분에 의해서 진행 순서가 LocalStrategy로 이동합니다.

LocalStrategy에서는 기본적으로 username과 password를 갖고있으며 이는 usernameField, passwordField로 custom할 수 있습니다.

매개변수로 받은 값을 이용하여 Database에서 해당 user가 있는지 확인하고 있으면 user 객체를 반환합니다.


user 객체가 반환이 되면 serializeUser로 진행 순서가 이어지며 위 코드에서는 user.deviceNumber를 세션에 저장합니다.

이전 포스트에서 express session을 redis와 연결하였기 때문에 redis store에 저장 됩니다.


저장된 세션 정보를 다시 가져올 때는 저장된 user.deviceNumber를 이용하여 해당 user의 정보를 가져와서 반환합니다.

여기서 deserializeUser는 모든 요청시에 통과하는 과정이므로 이 과정을 통해서 req.user를 사용할 수 있게 되며

해당 하는 사용자의 정보를 세션에서 가져와서 사용할 수 있게 됩니다.


이렇게 인증된 사용자를 만들 수 있으며 이를 통해서 url마다 인증이 필요한 기능에 체이닝을 하여 인증 여부를 물을수 있게 됩니다.




[ util/common.js ] 인증 여부 묻는 함수

/* check authenticated user */
module.exports.isAuthenticated = function isAuthenticated(req, res, next) {
if (!req.user) {
return res.status(401).send({
code: 0,
'message': '로그인이 필요합니다'
});
}
next();
};




[ 인증이 있는 사용자만 게시글을 작성할 수 있도록 체이닝을 겁니다. ]

/* user */
router.post('/users', isAutenticated, user.create);


결과적으로 인증 과정을 통하면 req에 req.user로 해당 사용자의 정보를 접근할 수 있게 됩니다.


위 과정은  RedisStore에  passport session 을 저장하는 것입니다.


req.uesr = req.session.passport.user 는 동일한 값을 갖습니다.




- 끗 -

728x90
반응형
Comments