티스토리 뷰
회원가입 구현하기
▶ 구현할 회원가입 기능 설명
이메일, 이름, 패스워드의 간단한 정도만 사용
1) 회원가입 페이지 구현
2) script를 이용해 이메일 형식, 비밀번호 길이 및 비밀번호확인 문자열과 일치여부 확인
3) form을 이용해 post 요청 전송
4) 회원가입 처리 및 redirect
* 비밀번호 저장 시 암호화하여 저장 (Hash)
Hash
: 문자열을 되돌릴 수 없는 방식으로 암호화하는 방법
→ hash 출력값으로는 사용자의 원래 비밀번호를 알아낼 수 없음
→ 비밀번호의 Hash 값을 데이터베이스에 저장하고, 로그인 시 전달된 비밀번호를 Hash하여 저장된 값과 비교해 로그인을 처리
- Node.js의 기본제공 모듈인 crypto모듈을 사용하여 hash값을 얻을 수 있음
- 간단하게 sha1알고리즘을 사용하거나 보다 강력한 sha224, sha256 등의 알고리즘도 사용 가능
const hash = crypto.createHash('sha1');
hash.update(password);
hash.digest("hex");
▶ 회원가입 구현하기
1) 회원가입 페이지 만들기
...
form(action="/join" method="post" onsubmit="return check()")
table
tbody
tr
td 이메일
td: input(type="text" name="email")
tr
td 이름
td: input(type="name" name="name")
tr
td 비밀번호
td: input(type="password" name="password")
tr
td 비밀번호 확인
td: input(type="password" name="password_confirm")
tr
td(colspan="2")
input(type="submit" value="가입하기")
...
...
script.
function check() {
const email = document.querySelector('[name="email"]').value;
if (!/^\S+@\S+\.\S+$/.test(email)) {
alert('이메일 형식이 올바르지 않습니다.');
return false;
}
const password = document.querySelector('[name="password"]').value;
if (password.length < 8) {
alert("최소 8자리 이상의 비밀번호를 설정해 주세요.");
return false;
}
const passwordConfirm = document.querySelector('[name="password_confirm"]').value;
if (password != passwordConfirm) {
alert('비밀번호 확인이 일치하지 않습니다.');
return false;
}
return true;
}
2) 회원가입 요청 처리하기
- 비밀번호 hash 값 저장
- 이미 존재하는 회원인지 체크
- 가입완료 후 메인화면으로 redirect
router.post(... => {
const { email, name, password } = req.body;
const pwHash = getHash(password); // getHash는 crypto를 이용해 비밀번호를 암호화하도록 따로 만들어서 export한 함수
const exists = await User.findOne({ email });
if (exists) {
throw new Error('이미 가입된 메일입니다');
}
await User.create({
email,
name,
password: pwHash,
});
res.redirect('/');
});
// getHash 코드
const crypto = require('crypto');
module.exports = (password) => {
const hash = crypto.createHash('sha1');
hash.update(password);
return hash.digest("hex");
}
로그인 구현하기
▶ 로그인 기능 설명
1) 로그인 화면 구성하기
2) passport-local strategy로 로그인 구현하기
3) passport.js 설정하기
4) passport로 요청 처리하기
* Passport.js
: Express.js 어플리케이션에 간단하게 사용자 인증 기능을 구현하게 도와주는 패키지
→ 유저 세션 관리 및 다양한 로그인 방식 추가 가능
- passport는 다양한 로그인 방식을 구현하기 위해 strategy라는 인터페이스를 제공
- strategy 인터페이스에 맞게 설계된 다양한 구현체들이 있음 (facebook, google, ...)
- passport-local은 username, password를 사용하는 로그인의 구현체
▶ 로그인 기능 구현하기
1) 로그인 화면 구성하기
...
form(action="/auth" method="post" onsubmit="return check()")
table
tbody
tr
td 이메일
td: input(type="text" name="email")
tr
td 비밀번호
td: input(type="password" name="password")
tr
td(colspan="2")
td: input(type="submit" name="로그인")
...
...
script.
function check() {
const email = document.querySelector('[name="email"]').value
if (!email) {
alert("이메일을 입력해 주세요.");
return false;
}
const password = document.querySelector('[name="password"]').value
if (!email) {
alert("비밀번호를 입력해 주세요.");
return false;
}
return true;
}
2) passport-local strategy로 로그인 구현하기
const config = { // 아이디 패스워드 필드 설정 필수!
usernameField: 'email',
passwordField: 'password',
};
const local = new LocalStrategy(config, async (email, password, done) => {
try {
const user = await User.findOne({ email });
if (!user) {
throw new Error('회원을 찾을 수 없습니다.');
}
if (user.password !== password) { // user.password는 hash값이므로 입력받은 password도 hash값으로 만들어서 비교해야함
throw new Error('비밀번호가 일치하지 않습니다.');
}
// 세션에 저장되는 유저 정보의 최소화
done (null, {
shortId: user.shortId,
email: user.email,
name: user.name,
});
} catch (err) {
done(err, null);
}
})
3) passport.js 설정하기
- 작성한 strategy를 passport.use를 이용해 사용하도록 선언 필요
- passport.use를 이용해 strategy를 사용하도록 선언한 후
passport.authenticate를 사용해 해당 strategy를 이용해 요청을 처리할 수 있음
const local = require('./strategies/local');
passport.use(local);
4) passprot.js로 post 요청 처리하기
- passport.authenticate함수를 http 라우팅에 연결하면
: passport가 자동으로 해당하는 strategy를 사용하는 request handler를 자동 생성
- express-session과 passport.session()을 사용하면
: passport가 로그인 시 유저 정보를 세션에 저장하고 가져오는 동작을 자동으로 수행
--- routes/auth.js ---
router.post('/', passport.authenticate('local');
--- app.js ---
const session = require('express-session');
app.use(session({
secret: 'secret',
resave: false,
saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());
app.use('/auth', authRouter);
5) session 유저 활용하기
session을 이용해 user를 사용할 때 serializeUser 와 deserializeUser 설정 필요
→ 이는 세션에 user 정보를 변환하여 저장하고 가져오는 기능을 제공
(ex. 회원 id만 세션에 저장하고 사용 시 회원 정보를 디비에서 찾아서 사용)
※ 세션 사용 시 위 두 함수를 작성하지 않으면 passport 로그인이 동작하지 않음
passport.serializeUser((user, callback) => {
callback(null, user);
});
passport.deserializeUser((obj, callback) => {
callback(null, obj);
});
▶ 로그아웃 기능 구현하기
passport는 req.logout 함수를 통해 세션의 로그인 정보를 삭제하여 로그아웃 기능을 구현 가능
router.get('/logout', ... {
req.logout();
res.redirect('/');
});
▶ 로그인 확인 미들웨어
로그인을 필수로 설정하고 싶을 경우 미들웨어를 사용하여 체크 가능
function loginRequired(req, res, next) {
if (!req.user) {
res.redirect('/');
return;
}
next();
}
app.use('/posts', loginRequired, postsRouter);
Session Store
▶ Session 이란?
: 웹 서버가 클라이언트의 정보를 클라이언트별로 구분하여 서버에 저장하고
클라이언트 요청 시 Session ID를 사용하여 클라이언트의 정보를 다시 확인하는 기술
※ 클라이언트가 정보를 저장하고, 요청 시 정보를 보내는 Cookie와 대조됨
Session 작동 방식
서버는 세션을 생성하여 세션의 구분자인 Session ID를 클라이언트에 전달
→ 클라이언트는 요청 시 session id를 함께 요청에 담아서 전송
→ 서버는 전달받은 session id로 해당하는 세션을 찾아 클라이언트 정보를 확인
▶ Express.js의 Session & Session Store
- express-session 패키지를 사용하여 간단하게 session 동작을 구현 가능
→ 특별한 설정 없이 자동으로 session 동작 구현 (자동으로 session id를 클라이언트에 전달, session id로 클라이언트 정보 확인)
Session Store
: 세션을 저장하는 저장소
express-session 패키지는 session을 기본적으로 메모리에 저장 (프로세스가 종료되면 메모리에 저장된 세션들도 전부 삭제된다)
→ 따라서 현재 구현된 어플리케이션을 종료 후 다시 실행하면 모든 유저의 로그인이 해제됨
→ 혹은 서버가 여러 대가 있을 경우 서버 간 세션 정보가 공유되지 않음
▶ MongoDB를 Session Store로 사용하기
- connect-mongo 패키지를 이용해 MongoDB를 session store로 사용 가능
- connect-mongo 패키지는 express-session 패키지의 옵션으로 전달 가능
- 자동으로 session 값이 변경될 때 update되고 session이 호출될 때 find 함
- connect-mongo 패키지를 사용해 express-session 설정 시 store 옵션에 전달하고 mongoUrl을 설정
- 세션데이터를 몽고디비에 저장하고 관리하는 기능을 자동으로 수행
const MongoStore = require('connect-mongo');
app.use(session({
secret: 'SeCrEt',
resave: false,
saveUninitialized: true,
store: MongoStore.create({
mongoUrl: 'mongoUrl',
}),
}));
회원과 게시글 연동하기
▶ 너무 길어져서 다음 포스팅으로..
2022.08.05 - [🔩 Back-End/🟩 노드 | Node.js] - [NodeJS] Express와 MongoDB로 웹서비스 만들기 - 2 (2)
이 글은 엘리스 AI트랙 5기 강의를 들으며 정리한 내용입니다.
'개발공부 > 🟩 Node.js' 카테고리의 다른 글
[NodeJS] Express와 MongoDB로 웹서비스 만들기 - 3 (1) (0) | 2022.08.05 |
---|---|
[NodeJS] Express와 MongoDB로 웹서비스 만들기 - 2 (2) (0) | 2022.08.05 |
[NodeJS] Express와 MongoDB로 웹서비스 만들기 - 1 (2) (0) | 2022.08.02 |
[NodeJS] Express와 MongoDB로 웹서비스 만들기 - 1 (1) (0) | 2022.08.02 |
[NodeJS] Mongoose ODM (0) | 2022.07.31 |
프론트엔드 개발자 삐롱히의 개발 & 공부 기록 블로그