본문 바로가기
Security, Authentication/Authentication

[Authentication] Level 5 Passport.js 이용해 Cookies, Sessions 설치 | serialize, deserialize 란?

by CodeMia 2022. 2. 3.

Passport를 이용해서 쿠키와 세션 심는 법에 대해 알아보자. 

 

1. npm으로 다운받기 

npm install passport passport-local passport-local-mongoose express-session 

 

passport  https://www.npmjs.com/package/passport

passport-local  https://www.npmjs.com/package/passport-local

passport-local-mongoose  https://www.npmjs.com/package/passport-local-mongoose

express-session  (express-sessions 아님) https://www.npmjs.com/package/express-session

 


 

기본 시작 코딩 

앞에서 했던 bcrypt와 saltround를 지운다. 

post register, post login도 비운다.

const express = require("express");
const ejs = require("ejs");
const mongoose = require("mongoose")

const app = express();

app.use(express.static("public"));
app.set('view engine', 'ejs');
app.use(express.urlencoded({ extended: true }));

mongoose.connect("mongodb://localhost:27017/userDB", { useNewUrlParser: true });

const userSchema = new mongoose.Schema({
email: String,
password: String
});

const User = new mongoose.model("User", userSchema);

app.get("/", function(req, res) {
res.render("home")
});

app.get("/login", function(req, res) {
res.render("login")
});

app.post("/login", function(req, res) {

});

app.get("/register", function(req, res) {
res.render("register")
});

app.post("/register", function(req, res) {

});

app.listen("3000", function() {
console.log("Server is up and running on port 3000.")
});

 


 

2. 3 개의 패키지 불러오기 

session,

passport,

passport-local-mongoose 

 

 

 

3. sessions를 셋업한다.

app.use()들 아래와 몽구스 연결 위에 app.use(session())을 적어준다. 

세션 설치

 

 

 

 

4. passport를 초기 설정(initialize)을 하고, sessions를 관리하기 위해 passport를 사용한다.

session 아래에 위치해야 한다. 

 

 

5. userSchema를 셋업하고 passport local mongoose 를 사용한다. 

이 passport를 사용하기 위해서는 플러그인으로서 mongoose 스키마가 필요하다. 

mongoose encryption 패키지를 사용할 때와 비슷하다. 

 

 

 

passportLocalMongoose 플러그인 안에 해쉬와 솔트 몽구스를 사용하고 몽고디비 안에 유저를 저장한다

 

 

 

6. 바로 아래에 몽구스 model을 이용해 User를 생성한다.

 

 

 

7. passport-local Configuration을 한다. 

https://www.npmjs.com/package/passport-local-mongoose

 

 

passport.use(User.createStrategy());

passport-local-mongoose를 사용해 로컬 로그인 strategy

 

passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser()); 

그리고 나서  우리의 유저를 serialize하고 deserialize한다. 

 

 

 

위의 코드 순서대로 작성해야 작동한다. 

 


serialize / deserialize 란?

 

 

serialize / deserialize 는 session을 사용할 때만 필요하다.

serialize: 연재하다, 시리즈로 출간하다

namely: 즉 다시말해

crumble: 바스러지다. 허물어지다

 

serialize는?

쿠키를 만들고 그 안에 유저 신원확인을 넣는다

we tell it to serialize our user it basically creates the cookie and our users identifications into the cookie

 

deserialize는?

쿠키를 뽀개서 그 안에 든 메세지를 본다

deserialize it basically allows passport to be able to crumble the cookie and discover the message inside which is who this user is. 

 

 

 


 

register post 채우기

이제는 post route를 채워보자. 

 

지금은 모두 비워있는 상태이다.

 

 

passport-local-mongoose 패키지를 사용할 수 있다. 

https://www.npmjs.com/package/passport-local-mongoose

var User = mongoose.model('Users', UserSchema);

User.register({username:'username', active: false}, 'password', function(err, user) {
  if (err) { ... }

  var authenticate = User.authenticate();
  authenticate('username', 'password', function(err, result) {
    if (err) { ... }

    // Value 'result' is set to false. The user could not be authenticated since the user is not active
  });
});

 

 

app.post("/register", function(req, res) {
User.register({ username: req.body.username }, req.body.password, function(err, user) {
if (err) {
console.log(err);
res.redirect("/register");
} else {
passport.authenticate("local")(req, res, function() {
res.redirect("/secrets")
});
}
});
});

line 53  User.register()

이 메소드 passport-local-mongoose 패키지에서 왔다. 

새 User 를 만들고 또 저장할 필요없이 바로 mongoose와 바로 소통 가능하다. 

 

line 53  function(err, user)

새로 등록한 유저 

 

line 58  passport.authenticate()

만약 에러가 나면 다시 register 페이지로 가게한다.

에러가 안나면 passport를 이용해 유저를 authenticate 할 것이다. 

 

line 58  "local"

우리가 실행하고 있는 authentication의 타입이다. 

 

line 58 콜백함수  

authenticate을 성공하고 유저가 로그인 했는지 안했는지 체크할 수 있는 current logged in session? 을 저장한 쿠키를 셋업에 성공했을 때 콜백 함수를 호출한다. 

if authentication was successful and we managed to successfully setup a cookie that saved their current logged in session, so you will have to check to see if they're logged in or not. 

 

line 59

하지만  "/secret" 라우트는 만들지 않았다. 그래서 새로 만들어 준다. 

 

 

 

/secret 라우트 만들기 

app.get("/secrets", function(req, res){
if (req.isAuthenticated()){
res.render("secrets");
} else {
res.redirect("/login");
}
});

 

line 53 

url 주소에다가 localhost/secret을 쳤을 때 바로 페이지가 나오면 안되고 

authenticate이 된 경우만 secret 페이지가 보이게 해야한다. 

 

 

 

이제 브라우저로 가서 회원 가입을 해보자. 

 

user@passportlocalmongoose.com

123456

 

 

회원가입이 되었다.

 

 

 

데이터베이스에 저장이 잘 되었다. 

salt와 hash는 따로 설정한 것이 없지만 passport-local-mongoose 패키지가 자동으로 생성해 줘 저장된다. 

Robo3T

좀 더 자세히 보면 

 

 

 

 

이제 secret 페이지를 주소창에 치고 바로 가보면 

 

 

이미 athenticated해서 다시 로그인 할 필요없이

바로 secrets 페이지에 들어온 것을 볼 수있다. 

내 session ID를 저장한 쿠키 때문이다. 

 

 

 

크롬 브라우저 setting에서 cookie를 검색하고 

cookies and other site data를 들어간다. 

 

see all cookies and site data 를 보면 

 

 

localhost 쿠키가 있는 것을 볼 수 있다. 

 

 

좀 더 자세히 보면 

content 는 express-session 패키지로 만들어졌다. 

connect.sid 안에 이 쿠키가 있다. 

브라우저를 끄면 expire된다. 

 

 

그래서 크롬을 끄고 다시 로컬 호스트로 가면 

더 이상 authenticated 되지 않고 로그인 하라고 나온다. 

 

 

 

 

 

login post 채우기

그럼 이제 login post를 작성해보자 

 

 

line 74: 새 user 만든다

 

line 78: passport를 이용해서 이 user를 로그인 시키고 authenticate 시킬 것이다. 

이 때 passport에서 제공하는 login() 함수를 사용한다. 

 

line78: user 로그인 시킬 유저

 

line 82: 성공적으로 authenticate 되면 secrets 페이지로 가게한다. 

 

 

 

로그인을 해보자 

 

 

 

성공적으로 secrets 페이지에 들어갔다.

 

 

 

 

Log out 라우트 만들기 

로그 아웃 버튼 눌렀을 때 아무 것도 나오지 않는다. 

 

passport.js 문서를 참고하면 

https://www.passportjs.org/

 

 

그냥 logout() 함수를 사용하는 것을 알 수 있다. 

유저 세션을 끊고 deauthenticate 한다. 

deauthenticate our user and end that user session 

 

 

 

 

 

 

logout을 누르면

 

 

 

다시 홈으로 간다. 

 

 

 


 

 

const express = require("express");
const ejs = require("ejs");
const mongoose = require("mongoose");
const session = require('express-session');
const passport = require("passport");
const passportLocalMongoose = require("passport-local-mongoose")

const app = express();

app.use(express.static("public"));
app.set('view engine', 'ejs');
app.use(express.urlencoded({ extended: true }));

app.use(session({
secret: "Our little secret.",
resave: false,
saveUninitialized: false
}));

app.use(passport.initialize());
app.use(passport.session());

mongoose.connect("mongodb://localhost:27017/userDB", { useNewUrlParser: true });

const userSchema = new mongoose.Schema({
email: String,
password: String
});

userSchema.plugin(passportLocalMongoose);

const User = new mongoose.model("User", userSchema);

passport.use(User.createStrategy());

passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());

app.get("/", function(req, res) {
res.render("home")
});

app.get("/login", function(req, res) {
res.render("login")
});

app.get("/register", function(req, res) {
res.render("register")
});

app.get("/secrets", function(req, res) {
if (req.isAuthenticated()) {
res.render("secrets");
} else {
res.redirect("/login");
}
});

app.get("/logout", function(req, res) {
req.logout();
res.redirect("/");
});

app.post("/register", function(req, res) {
User.register({ username: req.body.username }, req.body.password, function(err, user) {
if (err) {
console.log(err);
res.redirect("/register");
} else {
passport.authenticate("local")(req, res, function() {
res.redirect("/secrets")
});
}
});
});

app.post("/login", function(req, res) {
const user = new User({
username: req.body.username,
password: req.body.password
});
req.login(user, function(err) {
if (err) {
console.log(err);
} else {
passport.authenticate("local")(req, res, function() {
res.redirect("/secrets")
});
}
});
});

app.listen("3000", function() {
console.log("Server is up and running on port 3000.")
});

 

 

 

 

 

댓글