React HOC(Higher Oder Component) Auth 인증체크
리액트 컴포넌트를 인자로 받아서 다른 리액트 컴포넌트를 반환하는 함수를 고차함수라고 한다.
파라미터로 컴포넌트를 받고, 함수 내부에서 새 컴포넌트를 만들어 리턴해준다.
리액트 페이지에서 회원만 진입할 수 있는 페이지, 또는 관리자 페이지 등 사용자 인증에 따라
접근하지 못하도록 할때 HOC을 사용할 수 있다.
그림과 같이 backend로 request 를 날려서 landing page에 들어와있는 사람의 상태정보를 가져온다.
Server
// server/index.js
app.get('/api/users/auth', auth, (req, res) => {
// 미들웨어를 통과한 후 실행되는 코드 => Authentication이 True 이다.
// 성공했으므로 user 정보를 제공해준다. 페이지에서 user정보를 이용할 수 있어 편하다.
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
})
})
먼저 서버쪽에서 구현했던 소스이다. 미들웨어 auth가 먼저 실행되게 된다.
// server/middleware/auth.js
const {User} = require('../models/User');
let auth = (req, res, next) => {
// 인증처리를 한다.
// 클라이언트 쿠키에서 토큰을 가져온다.
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에 넣어준다
req.token = token;
req.user = user;
next(); // 미들웨어이기 떄문에 next 해줘야 한다.
})
}
module.exports = { auth };
미들웨어에서 유저 인증을 수행하게 된다.
Client - Action
// client/src/_action/user_actions.js
export function auth() {
const request = axios.get('/api/users/auth')
.then(response => response.data)
return {
type: AUTH_USER,
payload: request
}
}
Client - Reducer
export default function (state = {}, action) {
switch (action.type) {
.
.
.
case AUTH_USER:
return { ...state, userData: action.payload }
break;
default:
return state;
}
Client - Auth Hoc
// client/src/hoc/auth.js
import { Axios } from 'axios';
import React, { useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { auth } from '../_action/user_actions'
export default function (SpecificComponent, option, adminRoute = null) {
// option
// null => 아무나 출입가능
// true => 로그인한 유저만 출입 가능
// false => 로그인한 유저는 출입 불가능
function AuthenticationCheck(props) {
const dispatch = useDispatch();
useEffect(() => {
dispatch(auth()).then(response => {
console.log(response)
if (!response.payload.isAuth) {
// 로그인하지 않은 상태
if (option) {
props.history.push('/login')
}
} else {
// 로그인한 상태
if (adminRoute && !response.payload.isAdmin) {
props.history.push('/')
} else {
if (option == false)
props.history.push('/')
}
}
})
}, [])
return (
<SpecificComponent />
)
}
return AuthenticationCheck
}
// client/src/App.js
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'
function App() {
return (
<Router>
<div>
<hr />
{/*
A <Switch> looks through all its children <Route>
elements and renders the first one whose path
matches the current URL. Use a <Switch> any time
you have multiple routes, but you want only one
of them to render at a time
*/}
<Switch>
<Route exact path="/" component={Auth(LandingPage, null)} />
<Route exact path="/login" component={Auth(LoginPage, false)} />
<Route exact path="/register" component={Auth(RegisterPage, false)} />
</Switch>
</div>
</Router>
auth.js 에서 사용자 인증에 따른 페이지 접근을 관리한다.
App.js 에서는 컴포넌트를 Auth로 감싸주고 option에 인자를 넣어 페이지들의 접근 권한을 컨트롤한다.
- option
- null => 아무나 출입가능
- true => 로그인한 유저만 출입 가능
- false => 로그인한 유저는 출입 불가능
'Study > react' 카테고리의 다른 글
[React] 회원가입 페이지 및 로그아웃 (0) | 2021.10.31 |
---|---|
[React] 로그인 페이지 (0) | 2021.10.31 |
[React] React Hooks (0) | 2021.10.27 |
[React] Redux (0) | 2021.10.27 |
[React] Concurrently (프론트, 백 서버 한번에 켜기) (0) | 2021.10.27 |