페이지 중에서 아무나 접근할 수 있는 페이지 또는 관리자만 접근할 수 있는 페이지, 로그인한 사람만 접근할 수 있는 페이지, 로그인을 했는데 또다시 로그인 페이지로 진입하는 등 페이지에 대한 권한이 각각 다르기 때문에 Auth를 확인해야 한다.
그러려면
HOC를 사용 !!const EnhancedComponent = higherOrderComponent(WrappedComponent);👩🏻💻 HOC는 함수형태이며, 다른 컴포넌트(WrappedComponent)를 받은 후에 새로운 컴포넌트(EnhancedComponent)를 반환하는 함수이다.
⭐ 동작 과정
1. HOC에서 BE로 req를 날린다.
2. 현재 페이지에 들어와있는 유저의 상태정보를 가져온다.
ex) 상태정보: 로그인이 되어있는 사람인지, 관리자인지 등등
3. 유저의 상태정보를 보고 페이지에 대한 권한이 있는지 판단한다.
app.get('/api/users/auth', auth ,(req,res)=>{
//여기까지 통과해 왔다는 의미는 Auth가 true라는 것
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
})
})
const { User }= require("../models/User")
let auth = (req, res, next)=> {
// client 쿠키에서 토큰을 가져온다.
let token= req.cookies.x_auth;
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 };
userSchema.statics.findByToken= function(token, cb){
var user= this;
jwt.verify(token,'secretToken', function(err, decoded){
// token을 디코드 해서 userId를 사용하여 DB에서 유저를 찾은 후,
// 쿠키에서 가져온 token과 DB에 보관된 token이 일치하는지 확인
user.findOne({"_id": decoded, "token": token})
.then((user)=>{
cb(null, user);
})
.catch((err)=>{
return cb(err);
})
})
}
👩🏻💻위의 세개의 컴포넌트를 해석하자면 !!
middleware > Auth.js에서 cookie에 저장된 token을 가져와서models > User.js에서 복호화- token을 복호화 하면 userId가 나옴
- userId를 이용해서 DB의 userCollection에서 유저를 찾은 후, 쿠키에서 가져온 token이 유저도 가지고 있는지 확인
- 이때 없으면 Auth False, 쿠키가 일치하면 Auth True가 됨
📢 HOC이 유저에게 어떤 권한이 있는지 확인하기 위해, server > index.js > auth router로 req를 보낸다.
import React, { useEffect } from 'react'
import { useDispatch } from 'react-redux'
import { useNavigate } from 'react-router-dom';
import { auth } from '../_actions/user_action';
export default function(SpecificComponent, option, adminRoute = null) {
function AuthenticationCheck(){
const dispatch= useDispatch();
const navigate= useNavigate();
useEffect(()=>{
dispatch(auth())
.then(response =>{
console.log(response);
// 분기처리
// 로그인 하지 않은 상태
if(!response.payload.isAuth){
if(option){
// 로그인 안한 사람이 로그인 한 사람만 접근 가능한 페이지에 들어갈 때
navigate('/login');
}
}else{
// 로그인 한 상태
// 관리자가 아닌데 관리자 페이지에 들어가려는 경우
if(adminRoute && !response.payload.isAdmin){
navigate('/');
}else{
// 로그인 한 사람이 로그인페이지나 회원가입 페이지에 접근할 때
if(option===false){
navigate('/')
}
}
}
})
},[])
return(
<SpecificComponent/>
)
}
return AuthenticationCheck
}
여기서 SpecificComponent, option, adminRoute = null 세개의 파라미터가 존재한다.
SpecificComponent는 HOC 컴포넌트 안에 넣을 컴포넌트를 뜻한다.
option은 누가 접근 가능한지를 나타낸다.
null : 누구든 접근 가능, true: 로그인한 사람만 접근 가능, false: 로그인한 사람은 접근 불가능
adminRoute는 관리자만 접근 가능함을 나타내며, true : 관리자만 접근 가능이지만 현재는 누구나 접근 가능한 null로 설정해두었다.
⭐ route.js
import React from 'react'
import { HashRouter as Router, Route, Routes } from 'react-router-dom';
import LandingPage from './components/views/LandingPage/LandingPage';
import LoginPage from './components/views/LoginPage/LoginPage';
import RegisterPage from './components/views/RegisterPage/RegisterPage';
import Auth from './hoc/auth';
export default function route() {
const AuthLandingPage = Auth(LandingPage, null);
const AuthLoginPage = Auth(LoginPage, false);
const AuthRegisterPage = Auth(RegisterPage, false);
return (
<>
<Router>
<Routes>
<Route path="/" element={ <AuthLandingPage /> } />
<Route path="/login" element={ <AuthLoginPage /> }/>
<Route path="/register" element={ <AuthRegisterPage /> } />
</Routes>
</Router>
</>
)
}
HOC은 컴포넌트들이 모두 모여있는 route.js에서 설정해주었다.
Auth 안에 있는 LandingPage, LoginPage, RegisterPage가 위에서 말한 SpecificComponent 파라미터이다. 또한, null과 false option 파라미터이다.
export async function auth(){
// get method는 body부분이 필요 없음
const request= await axios.get('/api/users/auth')
.then(response=> response.data)
return{
type: AUTH_USER,
payload: request,
}
}
case AUTH_USER:
return{...state, userData: action.payload}
break;
userData: action.payload에서 userData는 작명한 것, action.payload는 server > index.js의 auth router에 있는 유저의 정보 (isAuth, isAdmin, email 등)가 모두 담겨있다.
때문에, 로그인할 때 console을 확인해보면 server의 auth route에 있는 것들이 모두 나타난다.

위처럼 HOC 컴포넌트를 생성해주고 적용시키니까, 로그인을 한 사람은 Login, Register 페이지에 접근할 수 없도록 설정할 수 있었다.