9. vue 웹페이지 만들기
지난시간…
기존의 로그인 기능은 mySQL을 활용하지 않고 백엔드 코드에 데이터를 바로 저장하는 형태로 보안도 매우 취약하다.(심지어 비밀번호는 암호화를 하지 않았다.) 데이터를 웹페이지 내부에 숨기는 것은 좋은 방법이 아니라는 판단으로 인해 mySQL과 연동하여 로그인을 구현할 수 있도록 변경해야 할 필요가 있었다.
참고
[Node.js | Passport.js (passport-local) + MySQL](https://gaemi606.tistory.com/entry/Nodejs-Passportjs-passport-local-MySQL) |
이참에 조금 허술하게 공부한 get, post에 대하여 조금 더 자세히 공부해야겠다.
GET과 POST
GET
요청을 전송할 때 필요한 데이터를 body에 담지 않고 쿼드스크링을 통해 전송한다.
서버로부터 정보를 조회하기 위해 사용되는 메소드이다
URL의 끝에
?
와 함께 이름과 값으로 쌍을 이루는 요청 파라미터를 쿼리스트링이라고 한다.
POST
리소스를 생성/변경 하기 위해 사용된다.
POST는 데이터가 Body로 전송되고 눈에 보이지 않아 get보다 안전하다고 생각할 수 있지만 크롬 등의 개발자 도구에서 요청 사항을 확인할 수 있기 때문에 암호화를 해야 한다.
POST는 생성, 수정, 삭제에 사용할 수 있지만, 생성에는 POST, 수정은 PUT 또는 PATCH, 삭제는 DELETE가 더 용도에 맞는 메소드라고 할 수 있다.
LogIn 시스템 연결
[[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지 - 인프런 | 강의](https://www.inflearn.com/course/%EB%85%B8%EB%93%9C-%EA%B5%90%EA%B3%BC%EC%84%9C/dashboard) |
- inflearn node.js 강의에서 만들었던 nodebird 로그인 코드를 api 형태로 만들어 post와 get을 통해 vue 프론트엔드와 연결될 수 있도록 해본다.
- 백엔드는 기존에 만들었던 로그인 백엔드를 그대로 이용하여 변형하여 사용하도록 한다.
- 지금부터 백엔드에 여러 키들과 mysql 비밀번호 등을 저장할 예정이니 깃허브를 private로 돌려두었다.
- nodebird는 백엔드와 프론트엔드를 하나의 포트에서 동작시키기 때문에 현재 만들고 있는 웹페이지와 같이 두 개를 분리하기 위해서는 적절하게 코드를 고쳐야 한다.
app.js
기존의 api 호출은 /api/login 으로 등록되어 있지만, nodebird에서 개발한 로그인은 /api/auth 로 연결되어 auth/login 으로 아이디와 비밀번호를 post 한다.
app.use('/api/auth', authRouter)
login은 post를 통해 비밀번호가 일치하는지 여부로 각각의 결과에 맞는 값을 되돌려주고, get을 통해 현재 로그인 상태에 대한 정보를 받아올 수 있다.
routes/auth
const express = require('express');
const passport = require('passport');
const bcrypt = require('bcrypt');
const { isLoggedIn, isNotLoggedIn } = require('./middlewares');
const User = require('../models/user');
const router = express.Router();
router.post('/join', isNotLoggedIn, async (req, res, next) => { //로그인 안한 사람만 접근 가능
const { email, nick, password } = req.body; //기존에 이메일로 가입한 사람이 있나 체크
try {
const exUser = await User.findOne({ where: { email } });
if (exUser) {
return res.redirect('/join?error=exist');
}
const hash = await bcrypt.hash(password, 12); //해시화 해서 저장
await User.create({
email,
nick,
password: hash,
});
return res.redirect('/');
} catch (error) {
console.error(error);
return next(error);
}
});
router.get('/login', function (req, res, next) {
console.log('respond')
// console.log(req.user.dataValues)
if (req.isAuthenticated() && req.user) {
return res.json({
user: req.user.dataValues
});
}
// console.log(req.isAuthenticated())
return res.json({ user: null });
});
router.post('/login', isNotLoggedIn, (req, res, next) => {
passport.authenticate('local', (authError, user, info) => {
if (authError) {
console.error(authError);
return next(authError);
}
if (!user) {
// alert(res.redirect(`/?loginError=${info.message}`))
return res.redirect(`/?loginError=${info.message}`);
}
return req.login(user, (loginError) => {
if (loginError) {
console.error(loginError);
return next(loginError);
}
return res.redirect('/indexpage');
});
})(req, res, next); // 미들웨어 내의 미들웨어에는 (req, res, next)를 붙입니다.
});
router.get('/logout', isLoggedIn, (req, res) => {
console.log('logout')
req.logout();
req.session.destroy(); //세션쿠키를 지움
res.redirect('/');
});
router.get('/kakao', passport.authenticate('kakao'));
router.get('/kakao/callback', passport.authenticate('kakao', {
failureRedirect: '/',
}), (req, res) => {
res.redirect('/');
});
module.exports = router;
- 우선, 기존에 nodebird를 개발하면서 만들었던 로그인 코드 중, login get과 post를 연결할 것이다.
frontend-vue
<form method="post" action="api/auth/login">
<p class="text-white ">아이디</p>
<input type="text" name="email" v-model="email" />
<p class="text-white">비밀번호</p>
<input type="password" name="password" v-model="password" />
<p></p>
<button type="submit" class="text-white hover:text-yellow-500">
로그인
</button>
</form>
이대, post는 간단하게 form 태그에서 바로 동작할 수 있도록 연결해준다.
로그인이 동작했을 때 action의 주소를 통해 백엔드에 접근한다.
passport
로그인 버튼이 동작하면 backend auth/login을 통해 passport/index.js를 실행한다. passport 파일 내부에는 index.js 파일이 있으며, local()을 통해 localStrategy.js 에서 비밀번호의 일치 여부를 판단한다.
frontend-get
export default {
created() {
this.$http
.get("/api/auth/login")
.then((res) => {
const user = res.data.user;
console.log(user);
console.log(res);
console.log();
if (user) {
this.$store.commit("setUser", user);
}
})
.catch((err) => {
console.error(err);
});
},
computed: {
user() {
return this.$store.getters.user;
},
},
};
- 동일한 프론트엔드 로그인 vue 파일에 로그인 상태가 되었을 시, get을 통해 현재의 email과 닉네임을 가져올 수 있도록 한다. 이때 res는 백엔드의 get login에서 내보내는 데이터다.
backend get
router.get('/login', function (req, res, next) {
console.log('respond')
// console.log(req.user.dataValues)
if (req.isAuthenticated() && req.user) {
return res.json({
user: req.user.dataValues
});
}
// console.log(req.isAuthenticated())
return res.json({ user: null });
});
- 로그인 상태일 때, user.dataValues의 값을 프론트로 넘겨준다. 이때 데이터는 json 파일로 넘겨 프론트에서 email과 nick네임을 확인할 수 있게 한다.