- cookie-session은 브라우져에 server에서 req가 들어가면,
server에서 브라우저에게 id를 하나(session) 건네줌.
F12, application에서 확인 가능.
이것은 서버를 저장하거나, 서버를 껐다가 켜면 지워지는데,
이 세션을 mongoDB에 저장시키면, 서버를 저장하든,
끝다 키든, login상태를 유지시킬 수 있다.
매우 중요한 부분이죠!!1
1. src/server.js
import './db'
import Video from './models/Video'
import User from './models/User'
import express from 'express'
import session from 'express-session'
///session을 위해서 npm i express-session
import MongoStore from 'connect-mongo'
///session을 mongo에 save하기 위해서 npm i connect-mongo
import morgan from 'morgan'
import rootRouter from './routes/rootRouter'
import userRouter from './routes/userRouter'
import videoRouter from './routes/videoRouter'
import { localsMiddleware } from './middlewares'
///session에 user, session등의 정보를 저장하기 위해서 사용.
const PORT = 4000
const app = express()
const logger = morgan('dev')
///express는 반드시 app.~~~의 순서가 매우 중요하다!!!!
app.set('view engine', 'pug')
app.set('views', process.cwd() + '/src/views')
app.use(logger)
app.use(express.urlencoded({ extended: true }))
///req.body를 받기위해서 urlencoded
app.use(
session({
secret: 'hello',
resave: false, //true하면 req요청때마다, cookie만듬, false는 login떄만 만듬
saveUninitialized: false, ///위와 동일
store: MongoStore.create({ mongoUrl: 'mongodb://127.0.0.1:27017/jmtube' }),
///여기서 session을 MongoStore에 저장함.
})
)
///session을 사용하기 위한 문법!!!!잘 봐둘것!!!
///이것으로 인해서 브라우져에 접속하면, session(Id)을 하나 받음.
// app.use((req, res, next) => {
// res.locals.sexy = 'you' //pug파일에서 sexy로 접근가능
// res.locals.siteName = 'jmTube' //pug파일에서 siteName으로 접근가능
// console.log(res)
// res.sessionStore.all((error, sessions) => {
// console.log(sessions)
// next()
// })
// })
-------->session 처리과정을 보기 위해서 중간에 넣은 middleware.
-------->처리과정을 보기위한 것이므로, 실제로 코딩은 안해줘도 된다.
app.use(localsMiddleware) ///이부분이 매우 중요!!! 아래에서 확인.
///이 부분이 모든 router의 맨 위에 존재해야 아래 router에 다 적용됨.
app.use('/', rootRouter)
app.use('/videos', videoRouter)
app.use('/users', userRouter)
app.listen(PORT, () => console.log('Server start in 4000'))
2. src/middlewares.js
export const localsMiddleware = (req, res, next) => {
res.locals.loggedIn = Boolean(req.session.loggedIn)
res.locals.loggedInUser = req.session.user;
res.locals.siteName = 'jmTube'
console.log(res.locals)
next()
}
///res.locals는 localstorage처럼, data들을 담아주는것
///일종의 context에 token을 담아서 req떄마다, token을 같이 보내주는것과 비슷
///res.locals.loggedIn에 true, false정보를 담고,
///res.locals.loggedInUser에 user의 정보를 담고,
///res.locals.siteName에 name의 정보를 담아서,
///pug파일에서든 어디든 공유할 수 있음.
///res.locals에 담은 정보들은 위의
///import MongoStore from 'connect-mongo'를 이용해 mongo에 session을
///저장시키면, login기능을 계속 유지시킬 수 있음.
3.src/controllers/userController.js
import User from '../models/User'
import bcrypt from 'bcrypt'
export const getJoin = (req, res) => {
return res.render('createAccount', { pageTitle: 'Create Account' })
}
export const postJoin = async (req, res) => {
const { email, username, password, password2, location, name } = req.body
///createAccount.pug에서 email, username등등을 받아옴.
const exists = await User.exists({ $or: [{ username }, { email }] })
///username, email이 DB에 같은 값이 있는지 check함.
///두개 항목을 같이 체크할떄, $or을 사용함.
if (password !== password2) {
return res.status(400).render('createAccount', {
pageTitle: 'Create Account',
errorMessage: 'Password does not match.',
})
}
///입력된 2개의 password가 같은지를 check함.
if (exists) {
return res.status(400).render('createAccount', {
pageTitle: 'Create Account',
errorMessage: 'This username/email is already taken',
})
}
///username, email이 같은 값이 있으면, errorMessage날려줌.
--->위에서 $or을 쓰지 않고 username, email을 따로 체크하는경우
// const emailExists = await User.exists({ email: email })
// if (emailExists) {
// return res.render('createAccount', {
// pageTitle: 'Create Account',
// errorMessage: 'This Email is already taken',
// })
// }
--->username, email을 따로 check하는 경우.
try {
await User.create({
email,
username,
name,
location,
password,
})
return res.redirect('/login')
///여기까지 진행되었으면, User를 create함.
} catch (error) {
return res.status(400).render('createAccount', {
pageTitle: 'Create Account',
errorMessage: error._message,
})
}
}
///error있을 경우, errorMessage를 날려줌.
export const removeUser = (req, res) => res.send('remove')
export const editUser = (req, res) => res.send('editUser')
export const getLogin = (req, res) => {
res.render('login', { pageTitle: 'Login' })
}
///login POST구현.
export const postLogin = async (req, res) => {
const { username, password } = req.body
const user = await User.findOne({ username })
///username, password를 pug파일로부터 받아옴.
if (!user) {
return res.status(400).render('login', {
pageTitle: 'Login',
errorMessage: 'Username does not exist.',
})
}
///user가 없을 경우 errorMessage 리턴함.
const ok = await bcrypt.compare(password, user.password)
if (!ok) {
return res.status(400).render('login', {
pageTitle: 'Login',
errorMessage: 'Wrong Password',
})
}
///req.body로 받은 password를 bcrypt로, DB에 bcrypt화 되어
///저장되어 있는 password와 비교함.
///session에 아래 항목을 저장시키고, 마지막에 홈 path('/')로
///redirect함.
req.session.loggedIn = true
req.session.user = user
res.redirect('/')
}
export const logoutUser = (req, res) => res.send('logout')
export const seeUser = (req, res) => res.send('see user')