191111 사용자 인증 관련 미들웨어 Passport

sykim·2019년 11월 11일
0

PASSPORT

브라우저에 쿠키를 설정해주면 그 쿠키를 통해 사용자 ID(정보)등을 알 수 있다.
여기서 PASSPORT가 브라우저에서 쿠키를 가져와 인증이 완료된 유저 정보를 CONTROLLER에 넘겨주는 역할을 한다.

  • passport 미들웨어를 통해 페북, 깃헙, 구글, 스팀, 인스타그램, 위챗 등... 대부분의 서비스로부터 인증을 받을 수 있다
npm install passport

6.1 # 강의 정리

1. User model 생성

npm install passport-local-mongoose

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;
  • passportLocalMongoose에게 어떤 필드값을 username으로 할 것인지 결정해주는 옵션값: {usernameField:"email"}

2. passport.js 파일 생성

passport.js

import passport from "passport";
import User from "./models/User";

passport.use(User.createStrategy());

passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
  • passport-local을 이용해서 사용자인증방식(strategy), 즉 로그인 방식을 자동으로 만들어준다
  • serializeUser : 어떤 필드가 쿠키에 포함될 것인지 알려주는 역할
    (지금 이 함수는 user.id만 담으라고 되어있다 ?)
  • deserializeUser : 그 쿠키를 어떻게 사용자로 전환을 할지 알려주는 역할
    (쿠키를 받아서 id로 사용자를 식별한다)

3. 컨트롤러에서 user 등록 (register)

userController.js

import routes from "../routes";
import User from "../models/User";
...
export const postJoin = async (req, res, next) =>{
    console.log(req.body)
    // const password = req.body.password;
    // const password2 = req.body.password2;
    const { body : { name, email, password, password2} } = req;
    if (password !== password2){
        // 400 : 잘못된 요청이라는 뜻이라 브라우저가 인식
        res.status(400);
        res.render("join",{ pageTitle : "Join" });
    } else{
        // reigister user
        try {
            // 2 사용자생성
            const user = await User({
                name,
                email
            });
            // 1 계정생성
            await User.register(user, password);
            next();
        } catch (error) {
            console.log(error);
            res.redirect(routes.home);
        }
    }
    
    // const { body : { name }} = req;
    // const searchingBy = req.query.term;
    // const { query : { term : searchingBy} } = req;
    
};

  • User 모델 연결
  • User 의 user,password를 등록 (계정 생성)
  • user 라는 곳에 name, email (사용자 생성)

4. postJoin을 미들웨어로 만들어 user 정보를 전역으로 만들기

userController.js

import passport from "passport";
import routes from "../routes";
import User from "../models/User";

export const postJoin = async (req, res, next) =>{
    console.log(req.body)
    // const password = req.body.password;
    // const password2 = req.body.password2;
    const { body : { name, email, password, password2} } = req;
    if (password !== password2){
        // 400 : 잘못된 요청이라는 뜻이라 브라우저가 인식
        res.status(400);
        res.render("join",{ pageTitle : "Join" });
    } else{
        // To Do : reigister user
        try {
            const user = await User({
                name,
                email
            });
            await User.register(user, password);
            next();
        } catch (error) {
            console.log(error);
            res.redirect(routes.home);
        }
        //res.redirect(routes.home);
    }
};
export const postLogin = passport.authenticate("local", {
    failureRedirect: routes.login,
    successRedirect: routes.home
});
  • argument에 next, next() 호출

globalRouter.js

...
globalRouter.post(routes.join, postJoin, postLogin);
...
  • PASSPORT 연결
  • postJoin을 미들웨어로 변경
  • globalRouter 에서 postJoin 미들웨어 추가 후 postLogin으로 가도록 수정
    (= 가입 완료 후 홈이 아닌, 바로 로그인이 이루어지는 로직)
    (= postLogin은 미들웨어(postJoin) 정보를 받아서 로그인시켜준다)

middlewares.js

...
export const localsMiddleware = (req, res, next) =>{
    res.locals.siteName = "weTube";
    res.locals.routes = routes;
    res.locals.user = req.user || null;
    console.log(req.user)
    next();
};
...
  • passport가 사용자를 로그인 시킬 때 passport는 user가 담긴 object를 요청(req)에도 올려준다
    (= 다른 템플릿들도 user에 접근할 수 있다)

PASSPORT & SESSION app에 연결

app.js

import passport from "passport";
...
import "./passport";
...

app.use(passport.initialize());
app.use(passport.session());
  • passport 초기와, session 이용하기
npm install express-session

app.js

import passport from "passport";
import session from "express-session";
...
import "./passport";
...
app.use(
    session({
        secret: process.env.COOKIE_SECRET,
        resave: true,
        saveUninitialized: false
    })
);
app.use(passport.initialize());
app.use(passport.session());
  • secret 옵션 설정 : 쿠키에 들어있는 세션 id를 암호화한다

요약을 하자면...
1. 쿠키는 express로 보내지고 있다.
2. express는 session을 이용해서 그 쿠키를 가질 수 있고
우리는 passport를 통해서 session을 이용한다.
이 말은 곧, session이 가진 쿠키를 이용한다는 말과 같다.
3. 그리고 passport로 deserialize를 진행한다.
-> deserialize를 진행사항
3-1. 쿠키는 암호화된 id를 해독해서 실제 id를 찾고
3-2. 이 id는 passport로 넘어간다.
3-3. passport로 넘어가면 deserialize 함수가 실행이 되고 이 함수는 사용자를 식별한다.
3-4. 식별한 사용자를 middleware나 routes의 요청 object에 할당한다
=> 어느 routes에서든 로그인한 사용자가 누구인지 체크할 수 있다

profile
블로그 이전했습니다

1개의 댓글

comment-user-thumbnail
2019년 11월 24일

서버를 재접속하면 로그아웃이 되어 버린다
(= 세션정보, 쿠키정보가 메모리에 저장되어 있기 때문)

1. connect mongo install

npm install connect-mongo

app.js

import MongoStore from "connect-mongo";

connect mongo를 사용해서 세션에서 데이터를 MongoStroe라는 저장소에 저장시킨다

2. 세션 설정에서 store 추가, 그 store(저장소)를 mongo와 연결

app.js

import mongoose from "mongoose";
...
const CookieStore = MongoStore(session);
...
app.use(
    session({
        secret: process.env.COOKIE_SECRET,
        resave: true,
        saveUninitialized: false,
        store: new CookieStore({mongooseConnection:mongoose.connection})
    })
);
답글 달기