Node ch.17 _ Ajax 이용하여 passport 로그인 구현

회원가입과 유사한, 로그인 로직에 필요한 HTML을 구성하고 필요한 Router설정을 할 수 있다.

  1. router/index.js 에 login 라우터 추가

    
     var express = require('express')
     var app = express()
     var router = express.Router()
     var path = require('path')
    
     var main = require('./main/main')
     var email = require('./email/email')
     var join = require('./join/index')
     var login = require('./login/index')
    
     router.get('/', function(req,res){
         console.log('indexjs . path loaded');
         res.sendFile(path.join(__dirname + "/../public/main.html"))
     });
    
     router.use('/main', main)
     router.use('/email', email)
     router.use('/join', join)
     router.use('/login', login)
    
     module.exports = router;
    
    
  2. router/login/index.js 경로&파일 생성 후 아래와 같이 입력 (join과 비슷)

    
     var express = require('express')
     var app = express()
     var router = express.Router()
     var path = require('path')
     var mysql = require('mysql')
     var passport = require('passport');
     var LocalStrategy = require('passport-local').Strategy;
    
    
     // DATABASE SETTING (Google Cloud SQL)
     var connection = mysql.createConnection({
         host     : '35.184.164.59',
         port     : 3306,
         user     : 'root',
         password : 'root',
         database : 'jsman'
     });
    
     connection.connect();
    
    
     router.get('/', function(req,res){
         var msg;
         var errMsg = req.flash('error');
         if(errMsg) msg = errMsg;
         res.render('login.ejs', {'message' : msg});
     })
    
     //passport.serialize
     passport.serializeUser(function(user, done) {
         console.log('passport session save : ', user.id)
         done(null, user.id);
     });
    
     passport.deserializeUser(function(id, done) {
         console.log('passport session get id: ', id)
         done(null, id);
    
     }); //세션값을 뽑아서 db에 전달
    
    
     passport.use('local-login', new LocalStrategy({
             usernameField: 'email',  //default 속성값
             passwordField: 'password', //default 속성값
             passReqToCallback: true
         }, function (req, email, password, done) {
             var query = connection.query('select * from user where email=?', [email], function(err,rows){
                 if(err) return done(err);
    
                 if(rows.length){
                     console.log('existed user')
                     return done(null, false, {message : 'Your email is already used'})
                 } else {
                     var sql = {email: email, password:password};
                     var query = connection.query('insert into user set ?', sql, function(err,rows) {
                         if(err) throw err
                         return done(null, {'email' : email, 'id' : rows.insertId});
                     })
    
                 }
             })
         }
     ));
    
     router.post('/', passport.authenticate('local-join', {
         successRedirect: '/main',
         failureRedirect: '/join',
         failureFlash: true })
     )
    
     module.exports = router;
    
    
  3. views/loing.ejs 파일 생성

    
     <html>
     <head>
         <meta charset="utf-8">
         <title>email form</title>
     </head>
     <body>
         <form action="/email/form" method="post">
             email : <input type="text" name="email"> <br/>
             passwd : <input type="password" name="password"> <br/>
    
         </form>
    
         <button class="ajaxsend">login</button>
    
         <div class="result"></div>
         <script>
             document.querySelector('.ajaxsend').addEventListener('click',
                 function() {
                     var email = document.getElementsByName('email')[0].value;
                     var password = document.getElementsByName('password')[0].value;
                     sendAjax('http://localhost:3000/email/ajax',{'email' : email, 'password' : password});
                 })
    
             function sendAjax(url, data){
                 var data = {'email' : data};
    
                 data = JSON.stringify(data);
                 var xhr = new XMLHttpRequest();
                 xhr.open('POST', url);
                 xhr.setRequestHeader('Content-Type', "application/json"); //서버로 json형태로 보낸다는걸 나타내주기위해
                 xhr.send(data);
    
                 xhr.addEventListener('load', function(){
                     //console.log(xhr, responseText);
                     var result = JSON.parse(xhr.responseText);
                     var resultDiv = document.querySelector(".result");
                     if(result.result !== "ok") resultDiv.innerHTML = "Your email is not found"
                     else resultDiv.innerHTML = result.name;
                 });
             }
         </script>
    
     </body>
     </html>
    
    
    
  4. 여기까지의 결과확인

    이 상태에서 post 로 요청을 보내면 /router/login/index.js의 router.post() 에서 처리를 해주는데,

    ajax로 요청을 받았으므로 passport에서 제공하는 custom callback을 이용하여 json으로 응답을 처리할 수 있다

  5. Custom callback

    /router/login/index.js 에 Custom callback 으로 post 수정

    
     var express = require('express')
     var app = express()
     var router = express.Router()
     var path = require('path')
     var mysql = require('mysql')
     var passport = require('passport');
     var LocalStrategy = require('passport-local').Strategy;
    
    
     // DATABASE SETTING (Google Cloud SQL)
     var connection = mysql.createConnection({
         host     : '35.184.164.59',
         port     : 3306,
         user     : 'root',
         password : 'root',
         database : 'jsman'
     });
    
     connection.connect();
    
    
     router.get('/', function(req,res){
         var msg;
         var errMsg = req.flash('error');
         if(errMsg) msg = errMsg;
         res.render('login.ejs', {'message' : msg});
     })
    
     //passport.serialize
     passport.serializeUser(function(user, done) {
         console.log('passport session save : ', user.id)
         done(null, user.id);
     });
    
     passport.deserializeUser(function(id, done) {
         console.log('passport session get id: ', id)
         done(null, id);
    
     }); //세션값을 뽑아서 db에 전달
    
    
     passport.use('local-login', new LocalStrategy({
             usernameField: 'email',  //default 속성값
             passwordField: 'password', //default 속성값
             passReqToCallback: true
         }, function (req, email, password, done) {
             console.log(1);
             var query = connection.query('select * from user where email=?', [email], function(err,rows){
                 if(err) return done(err);
    
                 if(rows.length){
                     console.log('existed user')
                     return done(null, {'email' : email, 'id' : rows[0].UID})
                 } else {
                         return done(null, false, {'message' : 'Your login info is not found.'})
                 }
             })
         }
     ));
    
     // router.post('/', passport.authenticate('local-join', {
     //     successRedirect: '/main',
     //     failureRedirect: '/join',
     //     failureFlash: true })
     // )
    
     // Custom callback
     router.post('/', function (req, res, next) {
         passport.authenticate('local-login', function (err, user, info) {
             if(err) res.status(500).json(err);                   // 에러를 json으로 응답 주기
             if(!user) return res.status(401).json(info.message); // 유저가 없을 때에도 json으로 응답 주기
    
             req.logIn(user, function (err) {
                 if(err) {return next(err); }
                 return res.json(user);
    
             });
         })(req, res, next);
    
     })
    
     module.exports = router;
    
    
  6. login.ejs 수정

        
     <html>
     <head>
         <meta charset="utf-8">
         <title>email form</title>
     </head>
     <body>
         <form action="/email/form" method="post">
             email : <input type="text" name="email"> <br/>
             passwd : <input type="password" name="password"> <br/>
    
         </form>
    
         <button class="ajaxsend">login</button>
    
         <div class="result"></div>
         <script>
             document.querySelector('.ajaxsend').addEventListener('click',
                 function() {
                     var email = document.getElementsByName('email')[0].value;
                     var password = document.getElementsByName('password')[0].value;
                     sendAjax('http://localhost:3000/login',{'email' : email, 'password' : password});
                 })
    
             function sendAjax(url, data){
                 var data = {'email' : data};
    
                 data = JSON.stringify(data);
                 var xhr = new XMLHttpRequest();
                 xhr.open('POST', url);
                 xhr.setRequestHeader('Content-Type', "application/json"); //서버로 json형태로 보낸다는걸 나타내주기위해
                 xhr.send(data);
    
                 xhr.addEventListener('load', function(){
                     //console.log(xhr, responseText);
                     var result = JSON.parse(xhr.responseText);
                     var resultDiv = document.querySelector(".result");
                     if(result.email) resultDiv.innerHTML = "Welcome, " + result.email + "!"
                     else resultDiv.innerHTML = result;
                 });
             }
         </script>
    
     </body>
     </html>
    
    
    
  7. 여기까지 수정 완료하고 email과 password 항목 써주면,

    DB에 없는 email 입력 시 “Your login info is not found.” 출력

    DB에 있는 email 입력 시 “Welcome XXX@XXX.XXX !” 출력

    되야하는데 오류남 …

    401 (Unauthorized) "Missing credentials"

    이러한 오류가..힝입니다….