본문 바로가기

영어쌤의 놀이방_ 수퍼.코드.파티/리액트와 장고로 회원가입 관리 만들어욤

(6.2) 권한주기(Auth State & Private Routes)_ 영어쌤이 만드는 회원가입, 인증[CRUD] 만들어욤! 리액트와 파이썬 장고

반응형

(6.2) 권한주기(Auth State & Private Routes)_
영어쌤이 만드는 회원가입, 인증[CRUD] 만들어욤! 리액트와 파이썬 장고

안녕하세요? 죠니입니다. 바로 시작할게요!

- 아직까진 Add Lead(data 생성)과 Lead list(data list) 페이지가 숨겨지지 않고 전면에 공개되어 있습니다. 있어서는 안될 일이죠.

- 그래서 당연하지만 인증 받은 계정으로 접속시에만 해당 기능이 가능한 페이지로 넘기도록 작업을 할 것 입니다.

(10) Lead data 생성 화면 숨기기

입니다.

시작!


(10)  /src/components/common/PrivateRoute.js 파일 생성 및 작성

- Lead data 생성 및 리스트 페이지 숨기기 // 권한을 가진 계정만 접근 가능
- 필요한 기능들 가져오기

- 다음을 작성합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import React from "react";
import { Route, Redirect } from "react-router-dom";
import { connect } from "react-redux";
import PropTypes from "prop-types";
 
const PrivateRoute = ({ component: Component, auth, ...rest }) => (
    <Route
        {...rest}
        render={props => {
            return <Component {...props} />;
        }}
    />
);    
 
const mapStateToProps = state => ({
    auth: state.auth
});
 
export default connect(mapStateToProps)(PrivateRoute);
cs

(11) /src/components/App.js 에 Private Route 추가

- Private Route 기능을 App.js 파일로 가지고 오게 합니다.

- 그리고 다음과 같이 보호하길 위하는 페이지를 <PrivateRoute> 로 감싸줍니다.
- 실질적으론 일반적인 <Route> 를 <PrivateRoute> 로 수정해 주면 됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// App.js
import React, { Component, Fragment } from "react";
import ReactDOM from "react-dom";
import { HashRouter as Router, Route, Switch, Redirect } from "react-router-dom";
 
import { Provider as Alert Provider } from 'react-alert';
import AlertTemplate from 'react-alert-template-basic';
 
import Header from "./layout/Header";
import Dashboard from "./leads/Dashboard";
import Alerts from "./layout/Alerts";
import Login from "./accounts/Login";
import Register from "./account/Register";
import PrivateRoute from ".common/PrivateRoute";
 
import { Provider } from "react-redux";
import store from "../store";
 
// Alert Options
const alertOptions = {
    timeout: 3000,
    position: 'top center'
}
 
class App extends Component {
    render() {
        return (
            <Provider store={store}>
                <AlertProvider template={AlertTemplate} 
                {...alertOptions}>
                    <Router>
                            <Fragment>
                            <Header />
                            <Alerts />
                            <div className="container">
                                <Switch>
                                    <PrivateRoute exact path="/" component={Dashboard} />
                                    <Route exact path="/register" component={Register} />
                                    <Route exact path="/login" component={Login} />
                                </Switch>
                               </div>
                        </Fragment>
                    </Router>
                </AlertProvider>
            </Provider>
        );
    }
}
cs

(12) /src/components/common/PrivateRoute.js 수정

- Priovate Route를 통해 페이지를 숨겼다면 이제는 인증을 받은 계정만이 접근할 수 있게 해야 한다는 개념이 들어가야 합니다.
- 다음과 같이 PrivateRoute.js 파일을 수정해 주세요.

- 위와 같이 인증이 되었는지에 대해 작성을 마치고 저장을 한 뒤 Redux tool을 활용해 확인을 하면 다음과 같은 결과를 얻을 수 있습니다.

- 그리고 페이지를 새로고침 하면 인증을 받지 않은 상태에선 다음과 같이 로그인 페이지로 Redirect됩니다. 바로 연결된다는 것 입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// /src/components/common/PrivateRoute.js
import React from "react";
import { Route, Redirect } from "react-router-dom";
import { connect } from "react-redux";
import PropTypes from "prop-types";
 
const PrivateRoute = ({ component: Component, auth, ...rest }) => (
    <Route
        {...rest}
        render={props => {
            if(auth.isLoading) {
                return <h2>Loading...</h2>
            } else if(!auth.isAuthenticated) {
                return <Redirect to="/login" />;
            } else {
                return <Component {...props} />;
            }
        }}
    />
);    
 
const mapStateToProps = state => ({
    auth: state.auth
});
 
export default connect(mapStateToProps)(PrivateRoute);
cs

(13) /src/actions/types.js 코드 추가 작성 || 사용자 계정 로그인 유무 판별

- 우리는 지금 REST API를 만들고 있습니다.
- 그렇기에 사용자가 지금 로그인이 되어있는 상태인지 아닌지를 판별해야 합니다.

- 목표는 다음과 같습니다.
- 사용자가 인증을 받았는지 확인
-- 토큰이 있다면 토큰을 fetch(가지고 오는 것)한다
- 인증을 받았다면 user loaded, 아니라면 auth error가 나게 합니다.

1
2
3
4
5
6
7
8
9
// /src/actions/types.js
export const GET_LEADS = "GET_LEADS";
export const DELETE_LEAD = "DELETE_LEAD";
export const ADD_LEAD = "ADD_LEAD";
export const GET_ERRORS = "GET_ERRORS";
export const CREATE_MESSAGE = "CREATE_MESSAGE";
export const USER_LOADING = "USER_LOADING";
export const USER_LOADED = "USER_LOADED";
export const AUTH_ERROR = "AUTH_ERROR";
cs

(14) /src/reducers/auth.js

- 다음과 같이 사용자 계정 인증과 실패에 대한 코드를 추가 작성 해줍니다.

 - 그리고 default 코드 위에 다음의 코드도 작성해 줍니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// src/reducers/auth.js
import {
    USER_LOADING,
    USER_LOADING,
    AUTH_ERROR
} from '../actions/types';
 
const initialState = {
    token: localStorage.getItem('token'),
    isAuthenticated: null,
    isLoading: false,
    user: null
}
 
export default function(state = initialState, action) {
    switch(action.type)    {
        case USER_LOADING:
            return {
                ...state,
                isLoading: true
            }
        case USER_LOADING:
            return {
                ...state,
                isAuthenticated: treu,
                isLoading: false,
                user: action.payload
            }
        case AUTH_ERROR:
            localStorage.removeItem('token');
            return {
                ...state,
                token: null,
                user: null,
                isAuthenticated: false,
                isLoading: false
            };
        default:
            return state;
    }
}
 
cs

(15) /src/actions/auth.js 생성 및 작성 

- 인증을 위한 동작에 대한 코드를 작성합니다.

- auth.js 에는 작성할 코드들로 인증 동작을 실행합니다.

- Postman을 활용하여 테스트를 했을 때와 같은 동작이라고 보시면 되고 실제 코드에 쓸 내용도 Postman의 그것과 매우 유사합니다.

- 코드를 마저 작성합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// /src/actions/auth.js
import axios from 'axios';
import { returnErrors } from './messages';
 
import {
    USER_LOADED,
    USER_LOADING,
    AUTH_ERROR
} from './types';
 
// CHECK TOKEN & LOAD USER
export const loadUser = () => (dispatch, getState) => {
    // User Loading
    dispatch({ type: USER_LOADING });
 
    // Get token from state
    const token = getState().auth.token;
 
    // Headers
    const config = {
        headers: {
            'Content-Type''application/json'
        }
    }
 
    // If token, add to headers config
    if(token) {
        config.headers['Authorization'= `Toekn ${token}`;
    }
    
    axios.get('/api/auth/user', config)
        .then(res => {
        dispatch({
            type: USER_LOADED,
            payload: res.data
        });
    }).catch(err => {
        dispatch(returnErrors(err.response.data,
        erro.response.state));
        dispatch({
            type: AUTH_ERROR
        });        
    });
}
cs

(16) /src/components/App.js 코드 추가 작성

- 동작을 위한 코드도 작성하였으니 그 동작을 이제 App.js로 가져와 반영합니다.

결과화면

- Redux tool로 결과를 확인합니다.
- /src/actions/auth.js 에서 작성한 것과 같이 User loading, auth error, get error 등이 불러와 졌습니다.


이렇게 해서 제 6장인 Auth State & Private Routes가 마무리 되었습니다.

다음 포스팅은

7장 Frontend Authentication 입니다. 간략히 내용을 언급하겠습니다.

- Login Functionality(로그인 기능)
- Login - get a token (토큰 발급 받기)
- Token 확인이 되어 인증 받기

잠시 쉬었다가 마지막 장을 위해 돌아오겠습니다.

반응형