-
User Authentication like a Boss카테고리 없음 2020. 3. 18. 18:21
1. Local Authentication with Passport
1) npm install passport-local-mongoose 모듈 설치 (패스워드 확인, 설정 같은것들 자동으로 해줌)
2) npm i passport passport-local 모듈 설치 (로그인을 어떤 방식으로 할지 도와 주는 모듈)
models에 User 모델을 만들어주자.
>User.js
import mongoose from "mongoose"; import passportLocalMongoose from "passport-local-mongoose"; const UserSchema = new mongoose.Schema({ name: String, email: String, avatarUrl: String, facebookId: Number, githubId: Number }); UserSchema.plugin(passportLocalMongoose, { usernameField: "email" }); const model = mongoose.model("User", UserSchema); export default model;
위 User모델을 init.js에 연동시켜주자.
>init.js
import dotenv from "dotenv"; import "./db"; import app from "./app"; dotenv.config(); import "./models/Video"; import "./models/Comment"; import "./models/User"; const PORT = process.env.PORT || 4000; const handleListening = () => console.log(`✅ Listening on: http://localhost:${PORT}`); app.listen(PORT, handleListening);
어떤 strategy로(깃헙, 페이스북 등)으로 로그인하는지 로직을 만들어주자.
>passport.js (패스포트 설정 파일)
import passport from "passport"; import User from "./models/User"; passport.use(User.createStrategy()); passport.serializeUser(User.serializeUser()); passport.deserializeUser(User.deserializeUser());
여기서, createStrategy는 로그인 할때 필요한 여러 기능들의 숏컷 형식이라고 보면 된다.
serialize는 어떤 정보를 쿠키에 넣을 것인지 정하는 것이고, deserialize는 해당 쿠키정보를 백엔드로 넘겨주는 역할을 맡는다.
이제 Join 부분의 post에 관련 로직을 넣어주자.
>userController.js
import User from "../models/User"; export const postJoin = async (req, res) => { const { body: { name, email, password, password2 } } = req; if (password !== password2) { res.status(400); res.render("join", { pageTitle: "Join" }); } else { try { const user = await User({ name, email }); await User.register(user, password); } catch (error) { console.log(error); } // To Do: Log user in`` res.redirect(routes.home); } };
User 모델 import 후, User 모델의 name과 email값에 body에서 가져온 name과 email값을 넣어주자. (같은 단어는 한개만 써도됨)
2. 로그인 기능 이어서,,,
>userController.js
import passport from "passport"; import routes from "../routes"; import User from "../models/User"; export const getJoin = (req, res) => { res.render("join", { pageTitle: "Join" }); }; export const postJoin = async (req, res, next) => { const { body: { name, email, password, password2 } } = req; if (password !== password2) { res.status(400); res.render("join", { pageTitle: "Join" }); } else { try { const user = await User({ name, email }); await User.register(user, password); next(); } catch (error) { console.log(error); res.redirect(routes.home); } } }; export const getLogin = (req, res) => res.render("login", { pageTitle: "Log In" }); export const postLogin = passport.authenticate("local", { failureRedirect: routes.login, successRedirect: routes.home }); export const logout = (req, res) => { // To Do: Process Log Out res.redirect(routes.home); }; export const userDetail = (req, res) => res.render("userDetail", { pageTitle: "User Detail" }); export const editProfile = (req, res) => res.render("editProfile", { pageTitle: "Edit Profile" }); export const changePassword = (req, res) => res.render("changePassword", { pageTitle: "Change Password" });
PostJoin을 middleware로 만들어 주었다. Join후, postLogin 함수로 가게 하였다.(아래 라우터 참조) 그리고, postLogin함수에서는 로그인 실패 시 다시 로그인 화면, 성공 시 홈 화면으로 가게 하였다.
>globalRouter.js
import express from "express"; import routes from "../routes"; import { home, search } from "../controllers/videoController"; import { getJoin, getLogin, logout, postJoin, postLogin } from "../controllers/userController"; const globalRouter = express.Router(); globalRouter.get(routes.join, getJoin); globalRouter.post(routes.join, postJoin, postLogin); globalRouter.get(routes.login, getLogin); globalRouter.post(routes.login, postLogin); globalRouter.get(routes.home, home); globalRouter.get(routes.search, search); globalRouter.get(routes.logout, logout); export default globalRouter;
>app.js
import express from "express"; import morgan from "morgan"; import helmet from "helmet"; import cookieParser from "cookie-parser"; import bodyParser from "body-parser"; import passport from "passport"; import { localsMiddleware } from "./middlewares"; import routes from "./routes"; import userRouter from "./routers/userRouter"; import videoRouter from "./routers/videoRouter"; import globalRouter from "./routers/globalRouter"; import "./passport"; const app = express(); app.use(helmet()); app.set("view engine", "pug"); app.use("/uploads", express.static("uploads")); app.use("/static", express.static("static")); app.use(cookieParser()); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.use(morgan("dev")); app.use(passport.initialize()); app.use(passport.session()); app.use(localsMiddleware); app.use(routes.home, globalRouter); app.use(routes.users, userRouter); app.use(routes.videos, videoRouter); export default app;
>middlewares.js
import multer from "multer"; import routes from "./routes"; const multerVideo = multer({ dest: "uploads/videos/" }); export const localsMiddleware = (req, res, next) => { res.locals.siteName = "WeTube"; res.locals.routes = routes; res.locals.user = req.user || {}; next(); }; export const uploadVideo = multerVideo.single("videoFile");
req된 유저의 데이터가 req.user에 들어가게 하였다.
3. Sessions on Express
1) npm install express-session 모듈 설치 (session에 값을 저장해주는 역할)
>app.js 연동
import express from "express"; import morgan from "morgan"; import helmet from "helmet"; import cookieParser from "cookie-parser"; import bodyParser from "body-parser"; import passport from "passport"; import session from "express-session"; import { localsMiddleware } from "./middlewares"; import routes from "./routes"; import userRouter from "./routers/userRouter"; import videoRouter from "./routers/videoRouter"; import globalRouter from "./routers/globalRouter"; import "./passport"; const app = express(); app.use(helmet()); app.set("view engine", "pug"); app.use("/uploads", express.static("uploads")); app.use("/static", express.static("static")); app.use(cookieParser()); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.use(morgan("dev")); app.use( session({ secret: process.env.COOKIE_SECRET, resave: true, saveUninitialized: false }) ); app.use(passport.initialize()); app.use(passport.session()); app.use(localsMiddleware); app.use(routes.home, globalRouter); app.use(routes.users, userRouter); app.use(routes.videos, videoRouter); export default app;
>middlewares.js
res.locals.user = req.user || null; console.log(req.user);
req.user || null 로 수정. req.user 값은 미들웨어로 pug에서 사용 될 수 있다.
>header.pug
if !user
4. MongoStore and Middlewares
1) npm i connect-mongo 모듈 설치 (session data를 mongo에 연결 해주는 모듈)