index.js
로그인할때 체크해야하는 요소 순서대로 작성하고, 체크하는 요소가 false일때, error 메세지를 잘 뿌리고, true면 진행하도록 함
User.findOne
은 기본 함수이고,
{email: req.body.email}
는 postman 으로 보낼 때 body중에 key인 'email'의 값을 읽어오는 것임
const cookieParser = require('cookie-parser')
app.post('/api/users/login', (req, res) => {
//요청된 이메일을 DB에 있는지 찾고
User.findOne({ email: req.body.email }, (err, user) => {
if(!user) {
return res.json({
loginSucess: false,
message: "제공된 이메일에 해당하는 유저가 없습니다."
})
}
//있으면 비밀번호가 맞는건지 확인
user.comparePassword(req.body.password, (err, isMatch) => {
if(!isMatch)
return res.json({
loginSucess: false,
message: "비밀번호가 잘못되었습니다."
})
})
//같으면 Token 생성
user.generateToken((err, user) => {
if(err) return res.status(400).send(err);
//생성한 토큰을 user에 넣었고, 어딘가에 저장해야함 쿠키나 로컬 스토리지
res.cookie("x_auth", user.token)
.status(200)
.json({loginSuccess: true, userId: user._id})
})
})
})
user.comparePassword
는 함수를 User.js에 작성
입력받은 password를 암호화하고, 기존에 암호화된 값을 비교해서 일치하면 ture를 리턴
userSchema.methods.comparePassword = function(plainPassword, cb){
bcrypt.compare(plainPassword, this.password, function(err, isMatch) {
if(err) return cb(err)
cb(null, isMatch)
})
}
token을 생성해서 쿠키든 어디엔가 저장해두고, token이 일치할 때만, 승인된 페이지에 접속하는 용도로 쓸 수 있음
npm install jsonwebtoken --save
로 설치
https://www.npmjs.com/package/jsonwebtoken
사용방법은 해당 웹 문서에서
이런식으로 jwt를 먼저 require로 가져오고
token을 sign 함수로 생성해준다
User.js 에 아래와 같이 작성해주고
const jwt = require('jsonwebtoken');
userSchema.methods.generateToken = function(cb){
var user = this;
//json web token을 이용해서 토큰 생성
var token = jwt.sign(user._id.toHexString(), 'secretToken')
user.token = token
user.save(function(err, user){
if(err) return cb(err)
cb(null, user)
})
}
index.js에서 작성한 함수인 generateToken함수를 불러와 token을 생성해줌
생성한 토큰을 cookie에 저장해야하므로
npm install cookie-parser --save
해주고 index.js에서 해줬던 토큰생성하는 부분에
user.generateToken((err, user) => {
if(err) return res.status(400).send(err);
//생성한 토큰을 user에 넣었고, 어딘가에 저장해야함 쿠키나 로컬 스토리지
res.cookie("x_auth", user.token)
.status(200)
.json({loginSuccess: true, userId: user._id})
})
이렇게 해줄수 있게 된다
어떻게 관리하든 자유지만 server > middleware 폴더 하위에 auth.js를 만들었다
auth.js 에서 작성하는건데,
'쿠키에 저장한 토큰'과 'User 모듈'을 비교하는것임
User.findByToken
함수로 쿠키에 저장된 토큰 넣고 비교해서 에러체크
const { User } = require('../models/User')
let auth = (req, res, next) => {
//인증처리를 하는곳
//DB에서 가지고있는 토큰과 캐시에서 가지고 있는 토큰을 비교
//클라이언트 쿠키에서 토큰을 가져옴
let token = req.cookies.x_auth;
//토큰 복호화한 후, 유저 찾기
User.findByToken(token, (err, user) => {
if(err) throw err;
if(!user) return res.json({isAuth: false, error: true});
req.token = token;
req.user = user;
next();
})
}
module.exports = { auth };
User.findByToken
함수는 User.js쪽에서 Static으로 만들어준다
User.js
userSchema.statics.findByToken = function(token, cb){
var user = this;
//가져온 토큰을 decode => User Id가 나옴
jwt.verify(token, 'secretToken', function(err, decoded){
user.findOne({"_id": decoded, "token":token}, function(err, user){
if(err) return cb(err);
cb(null, user)
})
})
}
jwt.verify()
의 두번째 인자는 처음 토큰 생성할 때와 동일한 것으로 해줘야한다
토큰을 decode해서 나오는 값은 user ID가 나오게 되므로, 이 값으로 findOne()
함수로 인자를 찾아내는 로직임
index.js에 auth 호출하는 GET API 작성해서 성공, 실패하여 true 띄워줌
app.get('/api/users/auth', auth, (req, res) => {
res.status(200).json({
_id: req.user._id,
isAdmin: req.user.role === 0 ? false : true,
isAuth:true,
email:req.user.email,
lastname:req.user.lastname,
role:req.user.role,
image:req.user.image
})
})
isAuth와 isAdmin 등 값을 넣어주어 client 단에서 화면 접근할 때 체크하도록 쓰임
로그인보다는 매우 간단하게 가능
당연히 GET API이며, auth
를 해주는 이유는 로그아웃을 하려면 로그인이 되어있어야 하니까!
findOneAndUpdate
함수는 기본함수로 id로 찾아서 token를 빈 문자열로 초기화함으로써 해당 id의 토큰을 날려버린다
app.get('/api/users/logout', auth, (req, res) => {
User.findOneAndUpdate({_id: req.user._id}
, {token: ""}
, (err, user) => {
if(err) return res.json({success: false, err})
return res.status(200).send({
success: true
})
})
})
로그아웃 API호출하면 token이 초기화 되는지를 확인해본다
<로그아웃 API 호출 전>
<로그아웃 API 호출 후>
token이 초기화 된것을 봐주면 되겠다