Elice SW 2/TIL
DAY 34 - TIL(1)
자이구
2022. 5. 21. 23:06
회원가입 구현하기
- 관리자가 모든 회원의 비밀번호를 알 수 있음 -> 보안 취약점 발생
- Hash는 문자열을 되돌릴 수 없는 방식으로 암호화하는 방법
- Hash출력값을 이용해 사용자의 비밀번호를 알아낼 수 없음
- 비밀번호의 Hash값을 DB에 저장
- 로그인 시 전달된 비밀번호를 Hash하여 저장된 값과 비교해 로그인 처리
SHA1 - 사용법
const crypto = require('crypto');
module.exports = (password) => {
const hash = crypto.createHash('sha1');
hash.update(password);
return hash.digest("hex");
}
- hash.update() : 주어진 데이터로 해시를 업데이트하는데 사용
- hasj.digest() : 해시된 데이터를 인코딩 하는데 사용
- Node.js의 기본제공 모듈인 crypto 모듈을 사용하여 hash값을 얻을 수 있음
Passport.js
- Express.js 어플리케이션에 간단하게 사용자 인증 기능을 구현하게 도와주는 패키지
- 유저 세션 관리 및 다양한 로그인 방식 추가 가능
passport-local
- 다양한 로그인 방식을 구현하기 위해 strategy라는 인터페이스 제공
- strategy 인터페이스에 맞게 설계된 다양한 구현체들이 있음(facebook.,google)
- passport-local은 username, passport를 사용하는 로그인의 구현체
로그인 기능 구현하기
- 로그인 화면 구성
- passport - local strategy로 로그인 구현
- passport.js 설정
- passport로 요청 처리
passport - local strategy
./passport/strategies/local.js
const LocalStrategy = require('passport-local').Strategy;
const { User } = require('../../models');
const hashPassword = require('../../utils/hash-password');
const config = {
usernameField: 'email', // 'email' 필드 사용하도록 설정
passwordField: 'password' // 'password' 필드 사용하도록 설정
};
const local = new LocalStrategy(config, async (email, password, done) => {
try {
const user = await User.findOne({ email });
if (!user) {
throw new Error('회원을 찾을 수 없습니다.');
}
// 검색 한 유저의 비밀번호와 요청된 비밀번호의 해쉬값이 일치하는지 확인
if (user.password !== hashPassword(password)) {
throw new Error('비밀번호가 일치하지 않습니다.');
}
done (null, {
shortId: user.shortId,
email: user.email,
name: user.name,
});
} catch (err) {
done(err, null);
}
});
module.exports = local;
passport.js 설정
./passport/index.js
const passport = require('passport');
const local = require('./strategies/local')
module.exports = () => {
passport.use(local);
// local strategy 사용
};
- 작성한 strategy를 passport.use를 이용해 사용하도록 선언
- passport.use를 이용해 strategy를 사용하도록 선언한 후
- passport.authenticate를 사용해 해당 strategy를 이용해 요청을 처리할 수 있음
passport.js로 post요청하기
./routes/auth.js
const { Router } = require('express');
const passport = require('passport');
const router = Router();
// passport local 로 authenticate 하기
router.post('/',passport.authenticate('local') ,(req, res, next) => {
res.redirect('/');
});
module.exports = router;
- passport.authenticate 함수를 http 라우팅에 연결하면 passport가 자동으로 해당하는 strategy를 사용하는 request handler를 자동 생성 (로그인 처리 - > 세션에 user 저장)
app.js
const session = require('express-session');
const passport = require('passport');
app.use(session({
secret: 'elice',
resave: false,
saveUninitialized: true
}));
// passport initialize
app.use(passport.initialize());
// passport session
app.use(passport.session());
app.use('/auth', authRouter);
- exspress-session과 passport.session()을 사용하면 passport가 로그인 시 유저 정보를 세션에 저장하고 가져오는 동작을 자동으로 수행
session 유저 활용
./passport/index.js
const passport = require('passport');
const local = require('./strategies/local')
module.exports = () => {
passport.use(local);
// local strategy 사용
passport.serializeUser((user, callback) => {
callback(null, user);
});
passport.deserializeUser((obj, callback) => {
callback(null, obj);
});
};
- session을 이용해 user를 사용할 때에는 serializeUser 와 deserializeUser를 설정
- 세션에 user정보를 변환하여 저장하고 가져오는 기능을 제공
- 세션 사용 시 위 두 함수를 작성하지 않을 시 passport 로그인이 동작하지 않음
- serializeUser : 사용자 정보 객체를 세션에 아이디로 저장
- deserializeUser : 세션에 저장한 아이디를 통해 사용자 정보 객체를 불러옴
- id만 저장하면 세션 용량이 커지는 것을 막음
session 유저 활용
./routes/index.js
router.get('/logout', (req, res, next) => {
req.logout();
res.redirect('/');
});
- passport는 req.logout() 함수를 통해 세션의 로그인 정보를 삭제하여, 로그아웃 기능을 제공
로그인 확인 미들웨어
./middlewares/login-required.js
module.exports = (req, res, next) => {
if(!req.user){
res.redirect('/');
return;
}
next();
// 로그인이 안되어있다면 메인화면으로
// 로그인이 되어있다면 다음 미들웨어로
}
app.js
app.use('/posts', loginRequired ,postsRouter);