(앞서 회원가입 로직을 완료한 상태)
* 추가글: 정리를 하다보니까 이해가 조금 더 편한 상태가 되려면 server부터 참고해주세요.
먼저 클라이언트
//[client] signin.jsx
const onValue = (data) => {
axios.post('http://localhost:3000/auth/login', {
email: data.email,
pw: data.pw
}).then(res => {
localStorage.setItem('토큰', res.data.userToken)
// header에 토큰 넣는 로직
setInterceptor(res.data.userToken)
history('/main')
})
}
// 헤더에 토큰을 넣어줌
import axios from 'axios';
export const setInterceptor = (token) => {
if (!token) return false
axios.defaults.headers.common['Authorization'] = `Bearer ${token}`
return true
}
페이지를 새로고침해도 token값을 유지할 수 있도록 localstorage를 이용한다.
그리고 로그인 연장을 위해서 header에 token을 싣는다.
리액튼 메모리위에서 돌아간다.
여기서 새로고침을 하면 리액트가 재실행된다. (메모리가 다 초기화)
axios는 리액트에서 갖다 쓰는것이기 때문에 새로고침시 axios도 같이 초기화가 된다.
그래서 header에 있는 token값은 사라지게 된다.
useEffect(() => {
const fristToken = localStorage.getItem('토큰') //로컬스토리지 데이터 key에 '토큰'이있다면 값이 나와
console.log('fristToken: ', fristToken);
if (fristToken) {
setInterceptor(fristToken)
}
setIsInit(true)
}, [])
그렇다면, 리액트가 처음 렌더링 되는 시점에 (요청을 보내기 전에 토큰을 가로챔)
토큰을 header에 넣어준다.
자, 그럼 코드를 하나씩 살펴보자
먼저 로컬스토리지에 토큰이 들어가 있는 상태이다.
해당 토큰을 intercept 하자.
// 헤더에 토큰을 넣어줌
//utill.js
import axios from 'axios';
export const setInterceptor = (token) => {
if (!token) return false
axios.defaults.headers.common['Authorization'] = `Bearer ${token}`
return true
}
인터셉터 한 토큰을 가지고 함수를 하나 만들었다.
Config Defaults 값을 설정해준다.
글로벌 axios 기본(defaults) 설정 :
axios.defaults.headers.common['Authorization'] = `Bearer ${token}`
* bearer은 네트워크 단에서 손실 없이 그대로 전달하는 서비스를 뜻함
헤더에 제대로 인증이 나오는지 확인하기 위해서 test용 라우트에 header를 요청해보았다.
다행이 콘솔에서 헤더에 있는 인증토큰을 확인을 할 수 있었다!!
로그인 api 기능 구현 - server
// express
// auth.js
const { hash } = require('bcrypt');
var express = require('express');
var router = express.Router();
const { User } = require('../models/users');
const { getToken } = require('../util/authutil');
const bcrypt = require('bcrypt');
// 로그인
router.post('/login', function (req, res, next) {
const { email, pw: password } = req.body
User.findOne({ email }, (err, userInfo) => {
console.log('userInfo: ', userInfo);
// 1. 로그인한 이메일이 있는지 없는지
if (err) {
res.status(500).send('server error')
}
// 이메일이 있다면 암호화된 비번이랑 요청받은 비번이랑 비교
const match = bcrypt.compareSync(password, userInfo.password)
// true일 경우
if (match) {
// 토큰만들기
const matchToken = getToken(userInfo.toJSON())
res.json({ userToken: matchToken })
} else {
res.status(401).send('비번이 일치하지 않아요.')
}
})
});
module.exports = router;
* 메서드 중 findOne은 mongoDB에서 데이터 검색을 할 때 사용한다.
findOne은 한 객체만 검색하고 싶을 때 사용하는 메서드이다.
위 로직은 email에 맞는 userInfo 객체를 찾는것이다.
* email에 맞는 객체가 있을 경우 bcrypt.compareSync로 비교한다.
userInfo.password 객체와 암호화 된 password를 비교한 값을 변수에 저장한다.
* 해당 값이 true일 경우 token을 미리 만들어 놓은 getToen함수에서 가져와야 한다.
그런 후 해당 userToken을 json형태로 만든 후 응답시켜 준다.
(-> 이후로 clinet에서 token을 받게 됨 -> interceptor됨 -> header에 저장됨 -> 로그인이 연장가능)
jwt를 이용해서 token생성 - getToken 부분 만들기
const jwt = require("jsonwebtoken");
const secretKey = 'marking-access-secret-key'
const getToken = (payload) => {
const token = jwt.sign(payload, secretKey, { expiresIn: 60 * 60 * 24 })
return token
}
module.exports = { getToken }
npm install jsonwebtoken --save
https://www.npmjs.com/package/jsonwebtoken
jwt.sign(payload, secretOrPrivateKey, [options, callback])
sign 메소드를 통해서 payload와 secretKey , { 토큰이 유지될 시간} 을 합쳐주면 토큰이 생성된다.
payload: JSON 객체 리터럴, 문자열
secretKey: 해당 부분은 내가 임의로 넣는 글이다.
{expiresIn: } : 시간 범위를 나타내는 초 또는 문자열
남은 부분은 auth 미들웨어와 로그아웃 기능이다.
2탄으로 to be continued.....
'Framework > React' 카테고리의 다른 글
React.memo, useCallback, useMemo 이용한 최적화 (0) | 2023.07.24 |
---|---|
params를 쓸까 query를 쓸까? (1) | 2022.12.13 |
React 회원가입 API (로그인 기능 전) (0) | 2022.10.31 |
React.memo, useCallback(), useMemo() (0) | 2022.10.26 |
React Hook Form 회원가입 유효성 체크 (0) | 2022.10.24 |
댓글