일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- vuex map
- postcss
- flex
- SCSS use
- Vue
- intersection opserver
- 다른컴퓨터에서 git사용
- vue 이벤트 수신
- 프로그래머스 K_Digital Training
- 쌓임맥락
- 이벤트 수식어
- git 같은계정 다른 컴퓨터
- nextjs사용법
- 리스트 렌더링
- Spacer
- 프로그래머스 데브코스 프론트엔드
- KDT 프로그래머스 데브코스 프론트엔드
- SCSS import
- react next
- KDT 프로그래머스
- vue mixin
- netlify redirect
- SCSS forward
- 고양이 사진 검색기
- vue 지역 컴포넌트
- 리액트
- 프로그래머스 데브코스
- 프로그래머스 프론트엔드 데브코스
- SCSS extend
- 폼 입력 바인딩
- Today
- Total
혼자 적어보는 노트
[Node.js] 로그인 구현하기 / Express, MySQL 본문
로그인을 하게 될 경우 세션에 유저 정보를 추가하고 세션 id를 브라우저 쿠키에 저장하고
서버에 요청을 할 때마다 쿠키정보를 함께 전송함으로써 서버에서 어떤 유저가 요청을 보내는지
파악할 수 있다고 이론 적인 부분만 알고있었다.
하지만 직접 구현을 하려고 하니 생각보다 복잡한 인증 절차가 있다고 한다. (social 로그인시)
passport를 사용하여 간단하게 로그인을 구현해보고
머릿속에 개념에 대해 간단하게나마 저장을 해보려 한다.
📄 준비된 것
- 회원가입 기능 구현 완료. (DB에 User의 데이터가 있는 상태)
- 프론트에서 로그인 버튼 클릭 시 {email, password} 데이터 전달하는 코드 작성
- Node Express를 이용한 서버 세팅
- Sequalize를 사용하여 모델 세팅
- MySQL으로 연결하여 데이터를 넣을 테이블 세팅
이전에 회원가입을 진행했던 포스팅에 이어서
진행을 해보겠다.
📂 관련 라이브러리 설치
passport, passport-local
npm i passport passport-local
Passport란 Node.js용 Express 호환 인증 미들웨어이다.
요청을 인증하기위해 Strategy(전략)의 개념을 사용한다.
express-session, cookie-parser
npm i express-session cookie-parser
express-session: express에서 session을 사용할 수 있도록 해주는 패키지
cookie-paser: cookei헤더를 파싱하고 쿠키 이름들로 된 object key로 req.cookies를 채운다
passport 설정
passport/index.js
module.exports = () => {
// passport 설정
passport.serializeUser((user, done) => {
done(null, user.id); // 서버에 user.id 저장
});
passport.deserializeUser(async (id, done) => {
//여기서 id는 serializeUser의 done에서 보낸 user.id
try {
const user = await User.findOn({
where: { id },
});
done(null, user);
} catch (error) {
console.log(error);
done(error);
}
});
local();
};
index.js에서 passport 설정을 해주고
module.export로 해당 함수를 내보낸다.
serializeUser : 사용자의 정보 객체를 세션에 저장한다.
deserializeUser : 서버에 저장된 아이디(객체)를 통해서 DB에서 사용자 정보를 불러온다.
local.js파일을 생성하여 연결을 해준다.
🔗 config 파일 연결
app.js에 아래의 코드를 추가한다.
const passport = require("passport");
const session = require("express-session");
const cookieParser = require("cookie-parser");
const passportConfig = require("./passport");
passportConfig(); // app.js에 연결
app.use(
session({
saveUninitialized: false,
resave: false,
secret: process.env.COOKIE_SECRET,
})
);
app.use(cookieParser(process.env.COOKIE_SECRET));
app.use(passport.initialize());
app.use(passport.session());
passportConfig() : passport/index.js를 연결
passport.initialize(), passport.session() : express에서 passport를 사용할 때 config를 위해 가장 먼저 수행될 미들웨어
session()
- resave : request마다 기존에 있던 session을 계속 다시 저장
- saveUninitialized : uninitialized상태의 session을 강제로 저장
- secret: session id를 암호화 할 수 있는 key이다. * 외부에 노출되어서는 안됨!
passport/local.js
const passport = require("passport");
const { Strategy: LocalStragy } = require("passport-local");
const { User } = require("../models");
const bcrypt = require("bcrypt");
module.exports = () => {
passport.use(
new LocalStragy(
{
// req.body에 대한 설정
usernameField: "email", // req.body.email
passwordField: "password", // req.body.password
},
async (email, password, done) => {
try {
const user = await User.findOne({
where: { email },
});
if (!user) {
return done(null, false, { reason: "존재하지 않는 이메일입니다." });
// 클라이언트 에러
// 이 세가지의 매개변수들은 err, user, info로 전달된다.
}
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);
}
}
)
);
};
local.js에서 본격적인 Strategy(전략)을 생성한다.
일단 passport-local에는 Stategy가 있으며 이 후 소셜 로그인과 구분하기 위해 이름을 LocalStategy로 변경해준다.
LocalStategy
- 첫 번째 인자 : req.body에 대한 설정
usernameField : "email"에서의 email은 req.body.email와 같다.
- 두 번째 인자: 첫 번째 인자에 적은 email과 password, 그리고 done을 매개변수로 받는다.
done
- 첫 번째 인자 : DB조회 시 발생하는 서버 에러
- 두 번째 인자 : 요청 성공여부, 성공 시 return 할 값
- 세 번째 인자 : 클라이언트로 보낼 에러
passport에서는 직접적인 응답을 보내지 않고 done을 보낸다.
routes/user.js
const express = require("express");
const bcrypt = require("bcrypt");
const router = express.Router();
const { User } = require("../models"); // User model
const passport = require("passport");
router.post(
// POST /user/login
"/login",
(req, res, next) => {
passport.authenticate("local", (err, user, info) => {
// err, user, info ==> done으로 보낸 것들
if (err) {
console.log(error);
return next(error);
}
if (info) {
// client 에러
return res.status(401).send(info.reason);
}
return req.login(user, async (loginErr) => {
if (loginErr) {
console.log(loginErr);
return next(loginErr);
}
return res.status(200).json(user);
});
})(req, res, next);
}
);
전달 받은 데이터에 맞게
응답처리를 해준다.
Logout
router.post("/logout", (req, res) => {
req.logout();
req.session.destroy(); // 세션에 저장된 쿠키와 아이디 삭제
res.status(201).send("ok");
});
간단하게 logout()으로 구현하고 session에 저장된 쿠키와 아이디를 삭제하면 로그아웃이 가능하다.
따라하는 작업을 하면서도 종종 에러가 발생했는데
네트워크 탭이나 에러 메세지를 보고 해결을 할 수 있었다. ❗❗ 오타조심
참고
'NextJS' 카테고리의 다른 글
[Next.js] Image height auto 사용 (0) | 2022.07.30 |
---|---|
[Next.js] Link와 href (0) | 2022.07.29 |
[Node.js] nodemon 사용 해보기 / nodemon 안될 때 (0) | 2022.03.17 |
[Node.js] Route 분리하기 (0) | 2022.03.15 |
[Node.js] express 사용하기 (0) | 2022.03.15 |