먼저 이 글을 보기전에 선행으로 passport.js 사용기(passport-local) 전략짜기여기서 기본적인 passport.js 구현 흐름과 redux, redux-saga 의 기본적인 선행지식이 필요합니다.
로그인폼 onSubmit 함수:
const onFinish = (values) => {
const {email} = values;
const checkEmail = emailReg.exec(email);
if(checkEmail === null){
//이메일 형식 검사 (정규표현식으로 통한 검증)
return alert('이메일 형식 잘못 입력했습니다!');
}
dispatch({
type:LOG_IN_REQUEST, //redux-saga로 비동기 로그인 요청,
data:values // {email, password}
})
};
redux-saga,axios를 통한 로그인 정보 서버로 전달.
function logInAPI(data){
return axios.post('/user/local',data)
// axios 를 통한 서버에게 로그인 요청하기.
}
function* logIn(action){
try{
const result = yield call(logInAPI,action.data);
//서버에서 반환받은 user 정보 를 result에 반환.
yield put({
type:LOG_IN_SUCCESS,
data:result.data
// state 에 저장하기 위해 reducer로 전달해 준다.
})
}catch(err){
yield put({
// redux 액션으로 보내줌. put:dispatch라고 생각하면 편하다.
type:LOG_IN_FAILURE,
error:err.response.data,
})
}
}
function* watchLogIn(){//2.
yield takeLatest(LOG_IN_REQUEST,logIn);
//take 한번만 실행되고 이벤트 삭제된다. 이벤트 리스너 느낌을 준다.
}
export default function* userSaga(){//1
yield all([
fork(watchLogIn),
])
}
userRouter
router.post('/local',isNotLoggedIn, (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);
}
return req.login(user, async(loginErr)=>{
if(loginErr){
console.error(loginErr);
return next(loginErr);
}
const userWithoutPassword = await User.findOne({
where:{ id:user.id},
attributes:['id','nickname','email'],
include:[{
model: Effect,
attributes:['id','title','html','css'],
include:[{
model: User,
as: 'Likers'
},{
model: User,
attributes: ['id','nickname']
}]
}]
})
return res.status(200).json(userWithoutPassword);
//최종 프론트로 전달해줄 유저정보.
})
})(req,res,next);
});
local(): 로컥전략짜기.
module.exports = () =>{
passport.use(new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
}, async (email, password, done)=>{
try{
const user = await User.findOne({
where:{
email
}
});
if(!user){
return done(null,false,
{reason:'존재하지 않는 이메일입니다.'});
}
const compare = await bcrypt
.compare(password,user.password);
if(compare){
return done(null,user);
}
return done(null,false,
{reason:'비밀번호가 일치하지 않습니다.'});
}catch(error){
console.error(error);
return done(error);
}
}))
};
module.exports = () =>{
passport.serializeUser((user,done)=>{
done(null, user.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();
};
한번더 프로젝트를 이용해서 passport.js 를 통한 로그인 전략을 짜 보니 로그인 흐름을 더 구체적으로 이해한거 같다 아직은 cookie와session 을 완벽하게 이해를 못해서 추가로 공부할 계획이다.