passport는 node.js 미들웨어로서 사용자 인증을 구현해준다. 페이스북, 카카오 등 다양한 passport가 있지만 일단은 기본인 이메일을 통한 로그인을 구현해보려 한다. (check)
1. passport 설치
$ npm i passport passport-local
2. passport 세팅
passport 폴더 생성 후 index.js 파일(여기에 passport 설정) 생성
serializeUser, deserializeUser 이 두개가 passport를 설정하는 기능이고, local은 따로
const passport = require('passport');
const local = require('./local');
module.exports = () => {
passport.serializeUser(() => {
});
passport.deserializeUser(() => {
});
local();
};
passport/local.js 파일 생성
const passport = require('passport');
const { Strategy : LocalStrategy } = require('passport-local');
const { User } = require('../models');
const bcrypt = require('bcrypt');
module.exports = () => {
passport.use(new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
}, async (email, password, done) => {
try{
const user = await User.findOne({
where: { email : email }
});
if(!user){
return done(null, false, { reason : '존재하지 않는 사용자입니다!'}) // 서버 에러, 성공여부, 클라이언트 에러
}
// 비밀번호 비교
const result = await bcrypt.compare(password, user.password);
if(result){
// 로그인 성공
return done(null, user);
}
return done(null, false, { reason : '비밀번호가 틀렸습니다.' });
}catch(error){
console.error(error);
return done(error);
}
}));
};
Strategy의 이름을 LocalStrategy로 설정하는 이유는 나중에 구글이나 카카오 로그인을 구현할 때 구분을 쉽게하기 위해서이다.
로컬 로그인 전략
1. 객체 부분 : req body부분을 설정해준다.
usernameField: 'email', passwordField: 'password' (req body에 담긴 이름 그대로 써주면 됨 id면 id)
2. 함수 부분: 객체에서 받은 인자들을 그대로 갖고와서 사용한다 (email, password, done)
3. done (a, b, c)
a: 서버 에러, b: 성공 여부, c: 클라이언트 에러
3. passport 설정 적용
app.js
const passportConfig = require('./passport');
passportConfig();
4. login api에 적용
routes/user.js
const passport = require('passport');
router.post('/login', passport.authenticate('local', (err, user, info) => {
if(err){
console.error(err);
next(err);
}
});
LocalStrategy done이 콜백함수의 역할을 하여서 각 인자 값들을 리턴한다.
ex) passport.authenticate('local' , (err, user, info)) //해당 변수 이름은 자유롭게 설정해도 됨
- err : 서버 에러
- user : 성공했을시 데이터 or false
- info : 클라이언트 에러
→ 하지만 위와 같이하면 req, res, next를 사용할 수 없기 때문에 미들웨어를 확장(express 기법)해준다.
미들웨어 확장
router.post('/login', (req,res, next)=> {
passport.authenticate('local', (err, user, info) => {
if(err){
console.error(err);
return next(err);
}
if(info){
return res.status(401).send(info.reason);
}
// passport.login
return req.login(user, async(loginErr) => {
if(loginErr){
console.error(loginErr);
return next(loginErr);
}
return res.json(user);
})
})(req, res, next);
});
서버와 클라에러가 없고 passport login을 거치면 로그인 완료!
이젠 json객체를 프론트에게 전달해주면 된다
+++++++++++++++++++++++++++++
로그인을 했으면 로그인한 정보를 저장해줘야한다.
백서버에서는 유저 정보를 세션에 들고있고 프론트에서는 쿠키로 유저정보를 담아서 보내준다.
(보안 취약을 보완하기 위한 jwt토큰이나 여러 방식이 있지만 지금은 그냥 패스)
$ npm i express-session
$ npm i cookie-parser
app.js
const session = require('express-session');
const cookieParser = require('cookie-parser');
const passport = require('passport');
app.use(cookieParser('secret')); //secret은 꼭 숨겨야함
app.use(session({
saveUninitialized: false,
resave: false,
secret: 'secret', //secret은 꼭 숨겨야함
});
app.use(passport.initialize());
app.use(passport.session());
passport/index.js
const passport = require('passport');
const local = require('./local');
const { User } = require('../models');
module.exports = () => {
passport.serializeUser((user, done) => {
done(null, user.id); //세션에 id만 저장
});
// id로 유저 찾기
passport.deserializeUser(async (id, done) => {
try{
const user = await User.findOne({ where : { id }});
done(null, user);
}catch(error){
console.error(error);
done(error);
}
});
local();
};
dotenv
secretKey와 같은 노출되면 위험한 값들의 보안을 위한 라이브러리
$npm i dotenv
root디렉토리에 .env파일 생성 후 .env파일에 숨겨야 할 값들 입력
COOKIE_SECRET = secretkey12
DB_PASSWORD = secretkey123
app.js
//dotenv 세팅
const dotenv = require('dotenv');
dotenv.config();
app.use(cookieParser(process.env.COOKIE_SECRET)); //secret은 꼭 숨겨야함
app.use(session({
saveUninitialized: false,
resave: false,
secret: process.env.COOKIE_SECRET, //secret은 꼭 숨겨야함
});
app.use(passport.initialize());
app.use(passport.session());
tip) json파일에는 dotenv 적용 불가
config.json → js파일로 변경 후 module.exports로 감싸준다.
그 후 위 app.js방법과 똑같이 암호화된 값들 입력하면 끝!
'Dot Programming > Node.js' 카테고리의 다른 글
[Node.js] Cors 설정 ( credentials ) (0) | 2021.01.28 |
---|---|
[Node.js] node mysql 시퀄라이즈 연결하기, 엔티티 연관 관계 설정 (0) | 2021.01.25 |