해결된 질문
작성
·
467
0
안녕하세요 logout 기능을 구현했는데 아래 에러가 떠서 너무 힘들어서 질문드립니다.
postman으로 POST 메소드로 login에 성공하였고, 토큰이 생기는것을 확인했습니다.
그 후 바로 postman으로 GET 메소드로 /api/users/logout을 하려 하는데 아래와 같은 에러가 발생하네요 ㅠㅠ
제 깃헙 주소에서 전체코드를 보실 수 있습니다. https://github.com/kth990303/boiler-plate-prac
어디가 문제인지 잘 모르겠네요. 답변 부탁드립니다 ㅜㅜ 감사합니다.
TypeError: Cannot read property 'x_auth' of undefined
at auth (C:\Users\User\Desktop\web_workspace\boiler_plate\middleware\auth.js:6:29)
at Layer.handle [as handle_request] (C:\Users\User\Desktop\web_workspace\boiler_plate\node_modules\express\lib\router\layer.js:95:5)
at next (C:\Users\User\Desktop\web_workspace\boiler_plate\node_modules\express\lib\router\route.js:137:13)
at Route.dispatch (C:\Users\User\Desktop\web_workspace\boiler_plate\node_modules\express\lib\router\route.js:112:3)
at Layer.handle [as handle_request] (C:\Users\User\Desktop\web_workspace\boiler_plate\node_modules\express\lib\router\layer.js:95:5)
at C:\Users\User\Desktop\web_workspace\boiler_plate\node_modules\express\lib\router\index.js:281:22
at Function.process_params (C:\Users\User\Desktop\web_workspace\boiler_plate\node_modules\express\lib\router\index.js:335:12)
at next (C:\Users\User\Desktop\web_workspace\boiler_plate\node_modules\express\lib\router\index.js:275:10)
at C:\Users\User\Desktop\web_workspace\boiler_plate\node_modules\body-parser\lib\read.js:130:5
at invokeCallback (C:\Users\User\Desktop\web_workspace\boiler_plate\node_modules\raw-body\index.js:224:16)
at done (C:\Users\User\Desktop\web_workspace\boiler_plate\node_modules\raw-body\index.js:213:7)
at IncomingMessage.onEnd (C:\Users\User\Desktop\web_workspace\boiler_plate\node_modules\raw-body\index.js:273:7)
at IncomingMessage.emit (events.js:327:22)
at endReadableNT (internal/streams/readable.js:1327:12)
at processTicksAndRejections (internal/process/task_queues.js:80:21)
코드는 아래와 같습니다.
Auth.js (auth.js:6:29는 const token=req.cookies.x_auth 부분입니다.)
const { User } = require("../models/User");
const auth=(req, res, next)=>{
// 인증처리
// client cookie에서 토큰 가져오기
const token=req.cookies.x_auth;
// token을 jwt로 decoding
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.js (Token 생성, findByToken function 부분)
userSchema.methods.generateToken=function(cb){
const user=this;
const token=jwt.sign(user._id.toHexString(), 'secretToken');
user.token=token;
user.save(function(err, user){
if(err) return cb(err);
cb(null, user);
});
}
userSchema.statics.findByToken=function(token, cb){
const user=this;
jwt.verify(token, 'secretToken', function(err, decoded){
user.findOne({"_id": decoded, "token": token}, function(err, user){
if(err) return cb(err);
cb(null, user);
});
});
}
const User=mongoose.model('User', userSchema);
// 다른 파일에서도 이 모델을 쓸 수 있도록
module.exports={ User }
Index.js (/api/users/login, /api/users/auth, /api/users/logout)
app.post('/api/users/login', (req, res)=>{
// 요청된 이메일을 db에서 찾는다.
User.findOne({email: req.body.email}, (err, user)=>{
if(!user){
return res.json({
loginSuccess: false,
message: "Unvalid email"
});
}
// 요청된 이메일이 db에 있다면 비밀번호 일치여부 확인
user.comparePassword(req.body.password, (err, isMatch)=>{
if(!isMatch)
return res.json({
loginSuccess:false,
message:"Wrong password"
});
// 일치 시, 토큰 생성
user.generateToken((err, user)=>{
if(err) return res.status(400).send(err);
// 토큰을 쿠키에 저장
res.cookie("x_auth", user.token)
.status(200)
.json({
loginSuccess: true,
userId: user._id
});
});
});
});
});
// auth라는 미들웨어를 추가
// request를 받으면 call back function 호출 전에 middleware실행
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,
name: req.user.name,
lastname: req.user.lastname,
role: req.user.role,
image: req.user.image
});
});
app.get('/api/users/logout', auth, (req, res)=>{
console.log(req.user);
user.findOneAndUpdate({_id:req.user._id}, {
token: ""
}, (err, user)=>{
if(err) return res.json({
success: false,
err
});
return res.status(200).send({
success: true
})
})
})
아래는 postman 화면 결과입니다.
+) 전체적으로 수업시간의 코드는 이해가 되는데, 어떤 의식의 흐름으로 이렇게 작성하는지 신기할 때가 많습니다.
예를 들면 쿠키에서 토큰을 가져온다 할 때 let token=req.cookies.x_auth 에서 req에 cookies에서 쿠키 이름인 x_auth로 접근하면 바로 토큰이 나온다는 사실을 몰랐음.
이런 경우는 어떤 부분을 공부해야 할까요? 전체적으로 자바스크립트 실력이 붕 뜬 느낌입니다. (초보자라 질문이 좀 이상한 것 같기도 하네요...)
답변 2
1
깃헙에서 확인해보니 아마도 app에 cookieParser를 추가를 안하셔서 x_auth에 토큰정보가 제대로 안담기고 있는것같아요.
index.js에서 12번째줄 밑에
app.use(cookieParser());
추가해주시면 될거같습니다.
0
추가로 위 코드에 index.js의 /api/users/logout 라우터에서 user.findOneAndUpdate에서 User.findOneAndUpdate로 해주어 ReferenceError: user is not defined 이 에러도 없앴습니다.
감사합니다... !!