본문 바로가기
Framework/React

React 로그인 API _ 1

by cariño 2022. 10. 31.
728x90
반응형

(앞서 회원가입 로직을 완료한 상태)

* 추가글: 정리를 하다보니까 이해가 조금 더 편한 상태가 되려면 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.....

 

728x90

댓글