Passport-ローカル使用法(nodejs)


passport-local
passport-localは、nodejsからログインし、ブラウザCookieにセッションを格納し、Webサーバで認証するライブラリです.ログインをpassportレコードで処理する方法
必要なモジュール
 	"body-parser": "^1.19.2",
    "cookie": "^0.4.2",
    "cookie-parser": "^1.4.6",
    "cors": "^2.8.5",
    "express": "^4.17.3",
    "express-session": "^1.17.2",
    "install": "^0.13.0",
    "nodemon": "^2.0.15",
    "npm": "^8.5.1",
    "passport": "^0.5.2",
    "passport-local": "^1.0.0",
    "passport-session": "^1.0.2",
    "session-file-store": "^1.5.0"
	// session-file-store는 다른 DB로 대체가능
モジュール要件
必要なモジュールが必要です.
const express = require("express");
// session 사용할때 필요
const session = require('express-session');
// session을 저장할 때 필요
const FileStore = require('session-file-store')(session);
// cors 고려해서 응답시 필요
const cors = require('cors');
// 클라이언트의 쿠키를 웹서버가 파싱할 수 있도록 require
const cookieParser = require('cookie-parser');
// 클라이언트에서 post요청을 했을때 req.body로 데이터를 받을 수 있도록 require
const bodyParser = require("body-parser");
// passport와 passport-local
const passport = require('passport');
const Strategy = require('passport-local').Strategy;


const app = express();
必要なミドルウェア

app.use(cors({
  origin: true,
  credentials: true // 요청에 쿠키를 넣고싶으면 이 옵션 사용
}));


// body parse
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.use(express.urlencoded({ extended: true }));

app.use(cookieParser());


// 이 세션함수는 반드시 passport.session() 전에 사용해야한다
app.use(session({
  secret: 'secret key',
  resave: true,
  saveUninitialized: false,
  secure: false, 
  store: new FileStore() // 세션을 저장할 store를 할당해줌
}));

// passport 초기화
app.use(passport.initialize());
app.use(passport.session());
戦略を立てる
戦略、戦略という言葉は気まずいです.
ログインを実現するための戦略を立てるだけでいい.
let strategy = new Strategy({
  usernameField: 'email', 
  passwordField: 'password', 
  session: true, // session에 저장 여부
  passReqToCallback: true, // 이 옵션을 설정하면 아래 콜백 함수의 첫번째 파라미터로 req 객체 전달됨
}, (req, email, password, done) => {
  if (email === '[email protected]' && password === '1234') {
    let userInfo = {
      email: '[email protected]',
      name: '홍길동',
      birth: '1102.05.29'
    }
    done(null, userInfo);
  } else {
    done(null, false, { message: "Incorrect ID/PW" });
  }
});
passport.use(strategy);
passport.シーケンス化されたユーザーと逆シーケンス化されたユーザー
SerializeUserは、ログインに成功した後にセッションを保存するコードです.
逆シーケンス化ユーザは、セッションが存在する場合にセッション情報を提供するコードとみなすことができる.
セッションがある場合はreq.ユーザーとしてアクセスできます.
passport.serializeUser(function (user, done) {
 console.log("serializeUser user : ", user);
 done(null, user);
}); // 로그인 성공했을때 호출됌
passport.deserializeUser(function (user, done) {
 console.log("deserializeUser user : ", user);
 done(null, user); // 여기 유저는 serializeUser에서 done으로 넘겨준 user임
 // 여기서 최종으로 넘기면 세션에 저장되서 req.user로 사용가능하다?
}); // 모든요청마다 호출됌
ログイン処理ルータ
app.post('/login', (req, res, next) => {
  passport.authenticate('local', {
    successRedirect: '/',
    failureRedirect: '/' },
    (err, user, message) => {
      if (user !== undefined) {
        req.logIn(user, (err)=>{
          if(err)return next(err);
          res.json({ result: 'User have sesseion' });
        });
      }
    }
  )(req, res, next);
});
passport.authenticateの最初のパラメータは、ローカルポリシーを使用することです.
2番目のオブジェクトは、ログインに成功したか失敗したときにどのパスに移動するかを決定するためのオプションです.
3番目のパラメータコールバック関数は、ログイン属性公示シーケンス化ユーザを実行した後、コールバック関数の2番目のパラメータからユーザ情報を受信し、ログイン失敗時にコールバック関数の1番目のパラメータからerrを受信することができる.
ログアウト
app.get('/logout', (req, res) => {
  // console.log('/logout', req.session);
  req.logOut();
  res.json({ result: 'User have not sesseion' });
})
Authorization
app.get('/', (req, res) => {
  console.log('req.user', req.user);
  res.json({ userInfo: req.user});
});
ユーザー情報をクライアントから直接送信します.クライアントにはユーザー情報がなくても許可しなくてもいいです.ユーザー情報は許可できます.つまり、クライアント上で許可処理を行ってもいいし、サーバ上で以下の操作を実行してもいいです.
app.get('/', (req, res) => {
	if(req.user === undefined){
    	res.status(400).send('로그인해주세요');
    }else{
    	res.status(200).send('Authorizaion해주세요')
    }
})
完全なコード
const express = require("express");
const session = require('express-session');
const FileStore = require('session-file-store')(session);
const cors = require('cors');
var cookieParser = require('cookie-parser');
// var cookie = require('cookie');
const bodyParser = require("body-parser");

const app = express();

// middleware list
app.use(cors({
  origin: true,
  credentials: true
}));
/*
  Credentials(인증서) 이 있는 CORS 요청은 Client와 Server
  둘다 Credentials를 사용하겠다는 속성을 설정해줘야 통신이 가능
*/

app.use(express.urlencoded({ extended: true }));
app.use(cookieParser());
// 이 세션함수는 반드시 passport.session() 전에 사용해야한다
app.use(session({
  secret: 'secret key',
  resave: true,
  saveUninitialized: false,
  secure: false, // 이건 뭘까
  store: new FileStore()
}));

const passport = require('passport');
const Strategy = require('passport-local').Strategy;

// passport.use(strategy); 이후에 미들웨어를 사용해야함
app.use(passport.initialize());
app.use(passport.session());

let strategy = new Strategy({
  usernameField: 'email', // input name
  passwordField: 'password', //input name
  session: true, // session에 저장 여부
  passReqToCallback: true, // 이 옵션을 설정하면 아래 콜백 함수의 첫번째 파라미터로 req 객체 전달됨
}, (req, email, password, done) => {
  if (email === '[email protected]' && password === '1234') {
    let userInfo = {
      email: '[email protected]',
      name: '홍길동',
      birth: '1102.05.29'
    }
    done(null, userInfo);
  } else {
    done(null, false, { message: "Incorrect ID/PW" });
  }
});
passport.use(strategy);


/*
 serializeUser는 로그인 성공을 하면 세션을 저장해주는 코드이고,
 deserializeUser는 세션이 있을때 세션정보를 꺼내주는 코드라고 생각하면된다.
 세션이 있다면 req.user로 접근이 가능하다.
*/

passport.serializeUser(function (user, done) {
  console.log("serializeUser user : ", user);
  done(null, user);
}); // 로그인 성공했을때 호출됌
passport.deserializeUser(function (user, done) {
  console.log("deserializeUser user : ", user);
  done(null, user); // 여기 유저는 serializeUser에서 done으로 넘겨준 user임
  // 여기서 최종으로 넘기면 세션에 저장되서 req.user로 사용가능하다?
}); // 모든요청마다 호출됌

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json()); // 요놈이 들어가야 한다.

app.get('/', (req, res) => {
  console.log('req.user', req.user);
  // passport.authenticate('local', {}, (err, user, message)=>{
  //   console.log(user);
  // })
  res.json({ userInfo: req.user});
});


// passport.authenticate를 하면 req.login()함수가 자동 실행됌
app.post('/login', (req, res, next) => {
  console.log('/login', req.session);
  passport.authenticate('local', {
    successRedirect: '/',
    failureRedirect: '/' },
    (err, user, message) => {
      console.log("req.user : "+ JSON.stringify(req.user));
      if (user !== undefined) {
        console.log('app.post : ', user);
        req.logIn(user, (err)=>{
          if(err)return next(err);
          res.json({ result: 'User have sesseion' });
        });
      }
    }
  )(req, res, next);
});

app.get('/logout', (req, res) => {
  // console.log('/logout', req.session);
  req.logOut();
  res.json({ result: 'User have not sesseion' });
})


app.listen(80, () => {
  console.log('80포트 실행됌')
})