개발자를 향해...
[노드 리액트 기초 강의] #11 로그인 기능 with Bcrypt (1) ~ #14 로그아웃 기능 본문
[노드 리액트 기초 강의] #11 로그인 기능 with Bcrypt (1) ~ #14 로그아웃 기능
eugeneHwang1124 2021. 2. 15. 22:04#11 로그인 기능 with Bcrypt (1)
로그인 기능을 추가하기 위해 우선 로그인 router를 만들어주고 데이터 베이스 안에서 요청된 이메일을 찾고 이메일이 있다면 비밀번호가 입력된 것과 같은지 확인하고 비밀번호까지 같다면 token을 생성해 주도록 해야한다.
<index.js>
app.post('/login', (req,res)=>{
//요청 이메일을 데이터베이스에 있는지 확인
User.findOne({email:req.body.email}, (err, userInfo)=>{
if(!userInfo){
return res.json({
loginSuccess: false,
message:"해당 이메일이 존재하지 않습니다"
})
}
})
//이메일이 있으면 비밀번호가 같은지 확인
user.comparePassword(req.body.password, (err, isMatch)=>{
if(!isMatch)
return res.json({loginSuccess:false, message:"비밀번호가 틀렸습니다."})
//비밀번호가 같다면 token을 생성
})
})
그리고 User.js에 가서 다음 코드를 추가한다.
<User.js>
userSchema.methods.comparePassword=function(plainPassword, cb){
//입력받은 비밀번호plainPassword와 db의 암호화된 비밀번호cb를 같은지 비교한다. 이때 입력받은 비밀번호를 암호화해야한다.
bycrpt.compare(plainPassword, this.password, function(err, isMatch){
if(err) return cb(err), //비밀번호가 같지 않아 에러가 생기면, err를 콜백한다.
cb(null, isMatch) //isMatch가 true로 들어간다
})
}
여기의 comparePassword를 index,js에서 호출하게 된다.
#12 토큰 생성 with jsonwebtoken
토큰을 생성하기 위해 npm i jsonwebtoken를 터미널에서 실행시켜준다. jsonwebtoken은 토큰을 생성시켜준다.
사용자의 id에 별도의 문자를 넣어서 토큰을 생성한 뒤 나중에 해설할 때에는 별도의 문자를 넣어서 다시 사용자의 id를 가져온다.
User.js에 토큰을 생성하는 메서드를 만든다.
userSchema.methods.generateToken=function(cb){
//jsonwebtoken을 이용해 토큰을 생성한다.
var user=this;
var token= jwt.sign(user._id, 'secretToken')
user.token=token
user.save(function(err,user){
if(err) return cb(err)
cb(null,user)
})
}
index.js에서 메서드를 호출하면 user에 토큰을 가져오게 된다. 이때 받아온 토큰을 쿠키에 저장해보자. 쿠키에 저장하기 위해서 cookieParser가 필요하다. 따라서 터미널에 npm i cookie-parser를 실행시킨다. 그리고 다음과 같이 쿠키 파서를 통해 쿠키를 넣어준다.
app.post("/api/users/login", (req, res) => {
//요청 이메일을 데이터베이스에 있는지 확인
User.findOne({email:req.body.email}, (err, user)=>{
if(!user){
return res.json({
loginSuccess: false,
message:"해당 이메일이 존재하지 않습니다"
});
}
//이메일이 있으면 비밀번호가 같은지 확인
user.comparePassword(req.body.password, (err, isMatch)=>{
if(!user)
return res.json({loginSuccess: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})
});
});
});
});
#13 Auth 기능 만들기
페이지를 이동할 때마다 로그인 정보와 관리자 여부등을 알아야한다. 페이지를 이동할 때마다 클라이언트의 쿠키를 전달해서 데이터베이스의 데이터와 같은지 확인한다. 토큰 생성할 때 별도의 문자를 넣어서 토큰을 생성한다 했는데 반대로 클라이언트의 토큰을 가져와 별도의 문자를 빼면 유저의 id를 알 수 있다. 만약 id가 없거나 다르면 원하는 작업을 할 수 없도록 한다.
<index.js>
app.get('./api/users/auth', auth , (req,res)=>{ //auth라는 미들웨어를 추가한다. 미드웨어는 엔드포인트의 리퀘스트를 받고 콜백함수를 실행하기 전에 뭔가 해주는 것이다.
//여기까지 미들웨어를 통과해 왔단ㄴ 이야기는 Authentification이 true라는 말.
res.status(200).json({//여기에 클라이언트에 제공할 유져 정보를 넣어주면 된다.
_id:req.user._id,
//isAdmin은 유저가 role이 0이면 일반유저 0이아닌 다른거면 관리자. 이렇게 설정할 수 있다.
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
});
});
<User.js>
userSchema.statics.findByToken=function(token,cb){
var user=this;
//토큰을 decode 한다.
jwt.verify(token, "secretToken", function(err, decoded){
//유저 아이디를 이용해 유저를 찾고
//클라이언트에서 가져온 토큰과 db의 토큰이 일치하는지 확인
user.findOne({"_id":decoded,"token":token}, function(err, user){
if(err) return cb(err);
cb(null, user)
})
})
}
middleware 폴더를 생성하고 auth.js를 생성해준다.
<auth.js>
const { User } = require("../models/User");
//auth들을 정리한다.
let auth=(req, res,next)=>{
//인증처리를 진행
//우선 클라이언트 쿠키에서 토큰을 가져온다.
let token = req.cookie.x_auth;
//토큰을 복호화한 후 유저를 찾는다.
User.findByToken(token,(err,user)=>{
if(err) throw err;
if(!user) return res.json({ isAuth:false, error:true })
//토큰과 user를 사용할 수 있도록 하기 위해 여기서 선언해준다.
req.token=token;
req.user=user;
next();
})
//유저가 있으면 인증 okay
//유저가 없으면 인증 no
}
module.exports ={auth};
#14 로그아웃 기능
- 로그아웃 라우터 만들기
- 로그아웃 하려는 사용자를 데이터 베이스에서 찾음
- 해당 유저의 토큰을 지움(auth에서 데이터베이스에 토큰을 넣어주고 이것으로 클라이언트의 쿠키가 가지고 있는 토큰과 비교해 같은지 여부를 판단해 권한을 부여했기 때문에 데이터베이스의 토큰 자체를 지워주면 인증이 되지 않는다.)
우선 라우터를 만들어준다.
<index.js>
//auth를 넣는 이유는 이미 로그인 된 상태이기 때문에
app.get('./api/users/logout',auth,(res,req)=>{
User.findOneAndUpdate({_id:req.user._id},
{token:""},
(err,user)=>{
if(err) return res.json({success:false, err});
return res.status(200).send({
success:true
})
})
})
'웹 자바스크립트 공부 > ReactJS + node.js' 카테고리의 다른 글
[노드 리액트 기초 강의] #19 CRA to Our Boilerplate ~#22 CORS 이슈, Proxy 설정 (0) | 2021.02.17 |
---|---|
[노드 리액트 기초 강의] #15 리액트란 ? ~ #18 구조 설명 (0) | 2021.02.17 |
[노드 리액트 기초 강의] #6 SSH를 이용해 GITHUB 연결 ~ #10 Bcrypt로 비밀번호 암호화 하기 (0) | 2021.02.13 |
[노드 리액트 기초 강의] #1 소개 ~ #5 GIT 설치 (0) | 2021.02.13 |
[ReactJS로 영화 웹 서비스 만들기] #6 ROUTING BONUS (0) | 2021.02.10 |