본문 바로가기

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

(7.1) Frontend Authentication_ 영어쌤이 만드는 회원가입, 인증[CRUD] 만들어욤! 리액트와 파이썬 장고

반응형

7장 Frontend Authentication

안녕하세요? 죠니입니다.

이제 이번 React+Django+Redux Authentication의 마지막 주제가 되겠습니다.

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

바로 시작해 보겠습니다.


(1) /src/actions/types.js

- 로그인 성공, 로그인 실패에 대한 type 추가하기

- Code on Color Scripter


(2) /src/actions/auth.js

- auth.js 파일 내에 로그인 성공, 실패에 대한 코드를 추가합니다.
- 5, 6번째 포스팅에서 진행했던 토큰에 대한 코드와 매우 유사합니다.(복붙 하고 수정하는게 제일 빠름)

- Request Body 추가

- axios 코드 작성


(3) /src/reducers/auth.js

- Login Success, Login Fail 가져오기

- 로그인 실패(Login fail)은 기본적으로 Auth error와 같은 동작을 합니다. 그러므로 auth reducer에선 두 case 모두 같은 동작을 하도록 case 코드(동작이 실행되는 조건을 명시하는 코드)만 추가해 줍니다.

- 로그인에 대한 reducer를 추가 작성합니다.


(4) /src/components/accounts/Login.js

- 이제 우리는 로그인에 관한 동작을 호출하는 것을 작성해야 합니다.

- onSubmit 항목 코드 수정

- login을 했을 때를 위해 render에 redirection 설정해주기

- 결과확인

- 인증받지 않은 정보로 로그인 시도시에는 로그인 실패 메세지 받고 로그인 요청 반려
- 현재는 redux tool로만 보임

- 정상 로그인 // 로그인 성공

- isAuthenticated: true // 인증이 정상적으로 받아졌습니다.

-User 정보입니다.


Codes

이번 포스팅에서 진행한 코드들의 결과물 입니다.

/src/actions/types.js

1
2
3
4
5
6
7
8
9
10
11
// /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";
export const LOGIN_SUCCESS = "LOGIN_SUCCESS";
export const LOGIN_FAIL = "LOGIN_FAIL";
cs

/src/components/accounts/Login.js

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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// Login.js
import React, { Component } from "react";
import { Link, Redirect } from "react-router-dom";
import { connect } from "react-redux";
import PropTypes from "prop-types";
import { login } from "../../actions/auth";
 
export class Login extends Component {
state = {
username: "",
password: "",
};
 
static propTypes = {
    login: PropTypes.func.isRequired,
    isAuthenticated: PropTypes.bool
}
 
onSubmit = e => {
    e.preventDefault();
    this.props.login(this.state.username,
    this.state.password);
};
 
onChange = e =>this.setState({ [e.target.name]: e.target.value });
 
 
render() {
if (this.props.isAuthenticated) {
    return <Redirect to="/" />;
}
const { username, password } = this.state;
return (
 <div className="col-md-6 m-auto">
        <div className="card card-body mt-5">
           <h2 className="text-center">Login</h2>
          <form onSubmit={this.onSubmit}>
             <div className="form-group">
               <label>Username</label>
               <input
                 type="text"
                 className="form-control"
                 name="username"
                 onChange={this.onChange}
                 value={username}
             />
            </div>
            <div className="form-group">
              <label>Password</label>
              <input
                type="password"
                className="form-control"
                name="password"
                onChange={this.onChange}
                value={password}
              />
            </div>
            <div className="form-group">
              <button type="submit" className="btn btn-primary">
                Login
              </button>
            </div>
            <p>
              Do not have an account? <Link to="/register">Register</Link>
            </p>
          </form>
        </div>
      </div>
 
        );
    }
}
 
const mapStateToProps = state => ({
    isAuthenticated: state.auth.isAuthenticated
});
 
export default connect(mapStateToProps, { login })(Login);
cs

/src/reducers/auth.js

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
49
50
51
52
53
54
55
56
// src/reducers/auth.js
import {
    USER_LOADING,
    USER_LOADING,
    AUTH_ERROR,
    LOGIN_SUCCESS,
    LOGIN_FAIL
} 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_LOADED:
            return {
                ...state,
                isAuthenticated: treu,
                isLoading: false,
                user: action.payload
            }
        case LOGIN_SUCCESS:
            localStorage.setItem("token", action.payload.token);
            return {
                ...state
                ...action.payload,
                isAuthenticated: true,
                isLoading: false
            };
 
        case AUTH_ERROR:
        case LOGIN_FAIL:
            localStorage.removeItem("token");
            return {
                ...state,
                token: null,
                user: null,
                isAuthenticated: false,
                isLoading: false
            };
        default:
            return state;
    }
}
 
 
 
cs

/src/actions/auth.js

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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// /src/actions/auth.js
import axios from 'axios';
import { returnErrors } from './messages';
 
import {
    USER_LOADED,
    USER_LOADING,
    AUTH_ERROR
} from './typs';
 
// CHECK TOKEN & LOAD USER
export const loader = () => (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
        });        
    });
};
 
// LOGIN USER
export const login = (username, password) => dispatch => {
 
    // Headers
    const config = {
        headers: {
            'Content-Type''application/json'
        }
    };
 
    // Request Body
    const body = JSON.stringify({ username, password });
 
    axios.post('/api/auth/login', body, config)
        .then(res => {
        dispatch({
            type: LOGIN_SUCCESS,
            payload: res.data
        });
    }).catch(err => {
        dispatch(returnErrors(err.response.data,
        erro.response.state));
        dispatch({
            type: LOGIN_FAIL
        });        
    });
};
 
 
 
cs

이상입니다.

다음 (7.2)는 로그아웃기능에 대하여 다룰 것 입니다.

반응형