session방식으로 회원가입 기능을 만들어볼 것.
- 가입 기능
- 로그인 기능
- 로그인 완료시 세션 만들기
- 로그인 완료시 유저에게 입장권 보내줌
- 로그인여부 확인하고 싶으면 입장권 조회
터미널 열어 npm install express-session passport passport-local 입력하여 설치

라이브러리 셋팅을 위해 서버 파일 server.js에 아래 코드 넣어주자
const session = require('express-session')
const passport = require('passport')
const LocalStrategy = require('passport-local')
app.use(passport.initialize())
app.use(session({
secret: '암호화에 쓸 비번',
resave : false,
saveUninitialized : false
}))
app.use(passport.session())

secret은 세션의 document id는 암호화해서 유저에게 보내는 것으로 암호화에 쓸 비번을 넣는 곳
resave는 유저가 서버로 요청할 때마다 세션을 갱신할 것인지
saveUninitialized는 로그인을 하지 않아도 세션을 만들 것인지에 대한 것
라이브러리 찾아보고싶으면 express-session한 번 찾아보자.

이 컬렉션에 유저의 id와 pw를 보관할 document를 만들어주면 된다.
테스트용으로 하나 만들어두자.

login.ejs파일 하나 만들어서 /login접속시 로그인 페이지 보여줄 수 있도록!

참고로 input에 name속성에 username과 password라고 사용한 것은 passport 라이브러리를 사용하는 경우에는 name속성을 맞춰줘야 하기 때문이다.

app.post('/login', async (요청, 응답, next) => {
제출한 id/pw가 DB에 있는거랑 일치하는지 확인하고 세션생성
})
이렇게 해주면 되는데 passport 라이브러리를 설치했으니 사용해주도록 하자..!
app.use가 많은 곳 하단쯤에 아래 코드를 복사해서 넣어준다.
passport.use(new LocalStrategy(async (입력한아이디, 입력한비번, cb) => {
let result = await db.collection('user').findOne({ username : 입력한아이디})
if (!result) {
return cb(null, false, { message: '아이디 DB에 없음' })
}
if (result.password == 입력한비번) {
return cb(null, result)
} else {
return cb(null, false, { message: '비번불일치' });
}
}))

저 장황한 passport.use가 뭐하는 곳이냐면..
passport.use(new LocalStrategy(async (입력한아이디, 입력한비번, cb) => {
// 제출한 아이디/비번 검사하는 코드 적는 곳
}))
검사 로직 적는 곳..!
passport.authenticate('local')()사용하면 위 기능 실행됨!
만약 id/pw 외에 다른 것도 검증하고 싶다면
passReqToCallback 옵션으로 검증 가능하니 찾아보자..!


error: 에러시
user: 성공시 로그인한 유저 정보
info: 로그인이 실패했을 경우
app.post("/login", async (요청, 응답, next) => {
passport.authenticate('local', (error, user, info)=>{
if(error) return 응답.status(500).json(error)
if(!user) return 응답.status(401).json(info.message)
// 로그인 성공
요청.logIn(user, (err)=>{
if (err) return next(err)
응답.redirect('/') // 로그인 완료시 실행할 코드
})
})(요청, 응답, next)
});
이까지 하고 로그인을 해보면
Error: Failed to serialize user into session
이런 오류가 나오는데, 이 부분은 세션을 만들어주면 된다.
로그인하면 세션을 만들어주고,
세션 id가 담긴 쿠키를 보내주는 것을 해보자..!
passport.serializeUser를 사용하여 세션 생성을 해주자passport.serializeUser((user, done) => {
process.nextTick(() => {
done(null, 세션document에기록할내용)
})
})
해당 코드를 사용해주면 된다.

해당 코드는 로그인이 로그인이 성공하면 실행되는 요청.logIn이 실행될때 자동으로 실행된다.

위의 요청.logIn부분~!
세션document에기록할내용에는 해당 데이터가 기록된 세션 document를 메모리(DB연결되어있으면 DB)에 발행해준다.
참고로 위에서 작성된 process.nextTick()는 node.js에서 특정 코드를 비동기적으로 처리해주고 싶을 때에 사용된다.
(위와 유사한 queueMicrotask()함수도 있다.)
passport.serializeUser((user, done) => {
console.log(user);
});
여기 user를 콘솔창에 출력해보면 터미널에 뜰 것이다.

뜬다.
그럼 이제 user.username이나 id나 pw나 넣어주기 편리할 것 같다.

이렇게 넣어주고 나서는 로그인 시 세션 document를 발행해주고, 그 document의 _id를 쿠키에 적어 보낼 것.
기본적으로 document에 세션 유효기간은 작성한 날 +2주라고 하는데, 이를 변경해주기 위해서는 상단에 cookie 옵션을 수정해주면 된다.

60 * 60 * 1000은 1시간,
60 * 1000은 60초동안 유지해준다.
이까지 설정을 하고 다시 로그인을 해보면..
Error: Failed to deserialize user out of session
이번에는 deserialize가 없다고 한다.
....... 넣어주자!

passport.deserializeUser((user, done) => {
process.nextTick(() => {
done(null, user);
});
});
deserialize는 유저가 보낸 쿠키를 분석해주는 역할이다.
쿠키가 이상이 없다면 현재 로그인된 유저 정보를 알려준다.
이후 다른 API에서 요청.user만 해줘도 유저 정보를 받아올 수 있게 해준다.(다만 해당 코드들 아래에 작성된 api에서만 가능)
문제점으로 세션 document에 적힌 유저정보를 그대로 요청.user에 담아주는 것인데, 정보가 시간이 지날 수록 달라질 수도 있다는 점에서 혼선이 있을 수 있어 DB조회 후에 보내주는 것이 낫다.
passport.deserializeUser(async (user, done) => {
let result = await db.collection('user').findOne({_id : new ObjectId(user.id)})
delete result.password
process.nextTick(() => {
done(null, result);
});
});

password는 넘겨주지 않는 것이 나으니 delete처리를 해주자.
위의 코드처럼 deserialize를 사용하면 최신 유저 정보를 담을 수 있게 된다.
이제 test를 해보자!!!

그리고 로그인도 해보자..

전송을 누르고,
브라우저 개발자도구에서 Application -> Cookies선택


로그인시 발급받은 쿠키 확인 가능하면 처리가 잘 된 것!!!

이후 다시 로그인창을 들어가보면

콘솔창에 현재 로그인 되어있는 유저 정보가 찍혀야한다.

지금 상태는 DB에 연결해둔 것이 아니라 서버가 재시작되면 로그인이 풀려버릴텐데, DB 연결에 관해서는 다음 포스팅에 이어해야겠다...
- 로그인에 성공하면 세션 document를 만들어 쿠키를 유저에게 보내줘야함
->passport.serializeUser()쓰면 자동으로 가능- 유저가 쿠키 제출시 확인해보기
->passport.deserializeUser()쓰면 자동으로 가능- 현재 로그인된 유저 정보 출력은
요청.user