[React] 인증 useSelector

jieun·2021년 4월 19일
0
post-thumbnail

디렉토리, 파일 생성

server/auth.js 생성
client/src/auth.js 생성
client/src/components/HomePage.js 생성

server/auth.js

const {User} = require('./models/User')

//인증 처리
let auth = (req, res, next) => {
    //1 클라이언트에서 토큰을 가져옴
    let token = req.cookies.x_auth

    //2 토큰을 복호화하고 유저를 찾음
    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()
    })

//3 유저가 있으면 인증, 없으면 인증안함
}

module.exports = { auth };

client/src/auth.js

import React, {useEffect} from 'react';
import {useSelector, useDispatch} from 'react-redux';
import {auth} from './_actions/user_action'

export default function (SpecificComponent, option, adminRoute = null) {
    //null => 아무나 출입이 가능한 페이지
    //true => 로그인한 유저만 출입이 가능한 페이지
    //false=> 로그인한 유저는 출입 불가능한 페이지

    function AuthenticationCheck(props){
        let user = useSelector(state => state.user);
        const dispatch = useDispatch();

        useEffect(() => {
            dispatch(auth()).then(response => {
                if(!response.payload.isAuth){
                    if(option) {
                        props.history.push('/sign_in')
                    }
                } else {
                    if(adminRoute && !response.payload.isAdmin) {
                        props.history.push('/home')
                    } else {
                        if(option === false)
                            props.history.push('/home')
                    }
                }
            })
        }, [])

        return (
            <SpecificComponent {...props} user={user} />
        )
    }

    return AuthenticationCheck
}

client/src/HomePage.js

import React from 'react';
import {withRouter} from 'react-router-dom'

function HomePage() {
    return (
      <div>
        <h2>환영합니다.</h2>
      </div>
    );
  }
  
  export default withRouter(HomePage)

client/components/Navbar.js 수정

import axios from 'axios';
import React, {useState} from 'react';
import {withRouter} from 'react-router-dom'
import {Link} from "react-router-dom";
import {useSelector} from "react-redux";
import "./Navbar.css"

const Navbar = (props) => {
    const [sign, setSign] = useState(true)
    const onClick = () => {
        setSign((prev) => !prev)
    }

    const user = useSelector(state => state.user)

    const onClickLogout = () => {
        axios.get('/api/users/logout')
        .then(response => {
            if(response.data.success) {
                props.history.push("/sign_in")
                } else {
                    alert("Failed to logout")
                }
            })
    }

    if (user.userData && !user.userData.isAuth) {
        return (
            <div>
                <nav>
                    <ul className="navbar">
                        <li><Link to="/">LOGO</Link></li>
                        {sign ? (
                            <li><Link to="/sign_in"><button onClick={onClick}>로그인</button></Link></li>
                            ) : (
                            <li><Link to="/sign_up"><button onClick={onClick}>회원가입</button></Link></li>
                        )}      
                    </ul>
                </nav>
            </div>
        )
    } else {
        return (
            <div>
                <nav>
                    <ul className="navbar">
                        <li><Link to="/home">LOGO</Link></li>
                        <li><button onClick={onClickLogout}>로그아웃</button></li>
                    </ul>
                </nav>
            </div>
            
            )
        }
    };

export default withRouter(Navbar)

client/App.js 수정

import React from "react";
import {BrowserRouter as Router, Switch, Route} from "react-router-dom";
import Navbar from './components/Navbar';
import LandingPage from './components/LandingPage';
import LoginPage from './components/LoginPage';
import RegisterPage from './components/RegisterPage';
import HomePage from './components/HomePage';
import Auth from './auth'

function App() {
  return (
    <Router>
      <div>
        <Navbar />
        <Switch>
          <Route exact path="/" component={Auth(LandingPage, false)} />
          <Route exact path="/sign_in" component={Auth(LoginPage, false)} />
          <Route exact path="/sign_up" component={Auth(RegisterPage, false)} />
          <Route exact path="/home" component={Auth(HomePage, true)} />
        </Switch>
      </div>
    </Router>
  );
}

export default App;

server/index.js 추가

//인증
const { auth } = require("./auth")
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
    })
})

server/models/User.js 추가

//인증 시 토큰과 디비의 토큰을 복호화하여 비교
userSchema.statics.findByToken = function(token, cb) {
    var 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)
        })
    })
}
profile
개발새발 블로그

0개의 댓글