[Node.js] Passport + sequelize + mariaDB 로그인/회원가입 구현

sangeun jo·2022년 3월 9일
0

프로젝트 구조

rootProject
ㄴconfig/
  ㄴpassport.js
ㄴcontroller/
  ㄴuser.js
ㄴmigrations/
ㄴmodels/
  ㄴ User.js
  ㄴ index.js
ㄴroutes/
  ㄴ user.js
ㄴseeders/
ㄴviews/
  ㄴuser/
  	ㄴjoin.ejs
    ㄴlogin.ejs
    ㄴmypage.ejs
ㄴindex.js

이메일을 유저 id로 사용함

I. mariaDB, sequelize 연동하기

config/dbconfig.json

{
  "development": {
    "username": "",
    "password": "",
    "database": "",
    "host": "",
    "dialect": "mysql"
  },
  "test": {
    "username": "",
    "password": "",
    "database": "",
    "host": "",
    "dialect": "mysql"
  },
  "production": {
    "username": "",
    "password": "",
    "database": "",
    "host": "",
    "dialect": "mysql"
  }
}

models/user.js


const Sequelize = require('sequelize');

module.exports = class User extends Sequelize.Model {
	static init(sequelize) {
		return super.init({
			usr_email: {
				type: Sequelize.STRING(50),
                primaryKey: true,
				allowNull: false,
				unique: true
			},
			usr_password: {
				type: Sequelize.STRING(60),
				allowNull: false,
				unique: false
			},
			usr_name: {
				type: Sequelize.STRING(20),
				allowNull: false,
				unique: true
			},
            created_at: {
				type: Sequelize.DATE,
				allowNull: false,
				unique: false
			},
            change_pass: {
				type: Sequelize.DATE,
				allowNull: true,
				unique: false
			},
			is_super: {
				type: Sequelize.CHAR(1), 
				unique: false,
				defaultValue: 'N' 
			}, 
            activate_yn: {
				type: Sequelize.CHAR(1),
				allowNull: true,
				unique: false,
                defaultValue: 'Y'
			},
		},
		{
			sequelize,
			timestamps: false,
			underscored: false,
			modelName: 'User',
			tableName: 'user',
			paranoid: false,
			charset: 'utf8mb4',
			collate: 'utf8mb4_general_ci'
		});
	}
};

models/index.js

const Sequelize = require('sequelize');

const User = require('./User');

const env = process.env.NODE_ENV || 'development';
const config = require('../config/dbconfig')[env];

const db = {};

const sequelize = new Sequelize(config.database, config.username, config.password, config);

db.sequelize = sequelize;
db.Sequelize = Sequelize;

db.User = User;
db.Project = Project; 
User.init(sequelize);
module.exports = db;

index.js

const express = require('express');
const bodyParser = require('body-parser');
const methodOverride = require('method-override');
const app = express();

//DB connect 
const { sequelize } = require('./models');
sequelize.sync({ force : false})
	.then(() => {
		console.log('connection success');
	})
	.catch((err) => {
		console.error(`connection fail - ${err}`);
	});
    
    
// Other settings
app.set('view engine', 'ejs');  
app.use(express.static(__dirname+'/public'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:true}));
app.use(methodOverride('_method'));

// Routes
app.use('/user', require('./routes/user'));
app.use('/', require('./routes/menu'));

const port = 3000;
app.listen(port, function(){
  console.log('server on! http://localhost:'+port);
});

II. 회원가입 구현

routes/user.js

const express = require('express');
const router = express.Router();
const { join } = require('../controller/user'); 

//회원가입 페이지
router.get('/join', (req, res) => {
    res.render('user/join'); 
})

//회원가입 진행
router.post('/joinProc', join); 

module.exports = router;

controller/user.js

const bcrypt = require('bcryptjs');
const User = require('../models/User'); 

exports.join = function (req, res) {

    let { email, password, passwordConfirmation, name } = req.body; 

    //비밀번호 암호화 
    password = bcrypt.hashSync(password)

    //저장
    var now = new Date(); 

    User.create({
        usr_email: email, 
        usr_password: password,
        usr_name: name,
        created_at: now
    })
    .then(()=>{
        res.redirect('/user/login');
    })
    .catch((err) => {
        throw err;  
    }) ;    
}; 

/views/user/join.ejs

<!DOCTYPE html>
<html>
    <head>
    </head>
    <body>
        <div>
            <h3>Join</h3>
            <form action="/user/joinProc" method="post">

              <div>
                <label>Email</label>
                <div>
                  <input type="text" id="email" name="email" value="">
                </div>
              </div>

              <div>
                <label for="password">Password</label>
                <div >
                  <input type="password" id="password" name="password" value="" >
                </div>
              </div>

              <div>
                <label for="passwordConfirmation" >Password Confirmation</label>
                <div>
                  <input type="password" id="passwordConfirmation" name="passwordConfirmation" value="">
                </div>
              </div>

              <div>
                <label for="username">Username</label>
                <div>
                  <input type="text" id="name" name="name" value="">
                </div>
              </div>

              <div>
                <button type="submit" >Submit</button>
              </div>
              </form>
        </div>
    </body>
</html>

III. passport 로그인 구현

config/passport.js

var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy; 
const User = require('../models/User'); 
const bcrypt = require('bcryptjs');

//로그인할 때마다 email 저장 
passport.serializeUser((user, done) => {
    done(null, user.usr_email); 
})

//email로 유저 객체 불러오기
passport.deserializeUser((email, done) => {
    User.findByPk(email).then( user =>{
        if(user) {
            done(null, user.get()); 
        } else {
            done(null, false); 
        }
    }); 
})

passport.use(
    new LocalStrategy(
        {
            usernameField: "email", 
            passwordField: "password", 
            passReqToCallback: true, 
        }, 
        async (req, email, password, done) => {
            User.findOne({
                where: {
                    usr_email: email
                }
            }).then((user)=> {
                if (user && bcrypt.compareSync(password, user.usr_password)) {
                    return done(null, user.dataValues); 
                } else {
                    return done(null, false); 
                }
            }).catch(err => {
                return done(err); 
            })
        }
    )
);

module.exports = passport;

index.js

//DB connect 
...
// 세션 
const session = require("express-session"); 
app.use(session({
  resave: false,
  saveUninitialized: true,
  secret: 'secret' 
}));

//passport 
const passport = require("./config/passport"); 

app.use(passport.initialize());
app.use(passport.session()); 
//모든 라우트에서 실행되는 미들웨어 
app.use((req, res, next) => {
  res.locals.isAuthenticated = req.isAuthenticated();  //locals에 저장하면 view에서 바로 사용가능
  res.locals.currentUser = req.user; 
  next(); 
})
...

//Other Settings

routes/user.js

//import modules 
...
//로그인 
router.get('/login', function (req, res) {
    res.render('user/login');
})

router.post('/loginProc',
    passport.authenticate('local',  {
        successRedirect: "/user/mypage", 
        failureRedirect: "/user/login", 
        failureFlash: true })
);

//마이 페이지 
router.get('/mypage', (req,res) => {
    const user = res.locals.currentUser 
    if (user === undefined) { //로그인X 
        res.render('user/login'); 
    } else {  
        res.render('user/mypage'); 
    }
}); 

//로그아웃 
router.get('/logout',function (req, res)  {
    req.logout();
    res.redirect('/');
});

...

//join route 

/views/user/login.ejs

<!DOCTYPE html>
<html>
  <head>
  </head>
  <body>
    <div>
      <h3>Login</h3>
      <form action="/user/loginProc" method="post">
        <div>
          <label for="email">Email</label>
          <div>
            <input type="text" id="email" name="email" value="">
          </div>
        </div>

        <div>
          <label for="password">Password</label>
          <div>
            <input type="password" id="password" name="password" value="">
          </div>
        </div>

        <div>
          <input type="submit" value="Submit">
        </div>

      </form>

    </div>
  </body>
</html>

/views/user/mypage.ejs

<!DOCTYPE html>
<html>
    <head>
    </head>
    <body>
        <div>
            <h3><%= currentUser.usr_name %> 님의 페이지</h3>
          
        </div>
    </body>
</html>
profile
코더가 아니라 개발자가 되자

0개의 댓글