反应路由器 PrivateRoute 不断重定向到登录

时间:2021-02-18 16:03:27

标签: reactjs django authentication django-rest-framework-simplejwt djoser

我刚刚在我的 django 和 react 应用程序中实现了基于令牌的身份验证,现在我想确保未经授权的用户无法访问我的页面。我通过使用 PrivateRoute 尝试了这个。令人讨厌的是,当您重新加载页面时,它一直将我发送到登录页面,然后该页面识别出我已获得授权,并将我送回首页。

因此,出于某种原因,当我刷新页面时,将 isAuthenticated 变量设置为 false 一秒钟。我试图通过在我的 auth.state 中创建一个 isLoading 变量来解决这个问题。这应该识别出身份验证尚未加载,并且应该等待检查 isAuthenticated 状态。

但是,当我重新加载页面时,它仍然会登录,然后回到主页,因为它需要一段时间才能识别 isAuthenticated 变量。有谁知道为什么会发生这种情况?

这是我的 PrivateRoute 文件

import React, { useState } from 'react';
import { Redirect, Route } from 'react-router-dom'
import { connect } from 'react-redux';

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);

在reducers/auth 文件中我声明initialState 应该是isLoading = false,然后我声明当AUTHENTICATION_LOADING 被调用时isLoading 应该是true。当身份验证成功或失败时,isLoading 设置为 false。

const initialState = {
    access: localStorage.getItem('access'),
    refresh: localStorage.getItem('refresh'),
    isAuthenticated: null,
    user: null,
    isLoading: false,
};

export default function(state = initialState, action) {
    const { type, payload } = action;

    switch(type) {
        case AUTHENTICATED_LOADING:
            return {
                ...state,
                isLoading: true,
            };
        case AUTHENTICATED_SUCCESS:
            return {
                ...state,
                isAuthenticated: true,
                isLoading: false,
            }
        case LOGIN_SUCCESS:
            localStorage.setItem('access', payload.access);
            localStorage.setItem('refresh', payload.refresh);
            return {
                ...state,
                isAuthenticated: true,
                access: payload.access,
                refresh: payload.refresh
            }
        case SIGNUP_SUCCESS:
            return {
                ...state,
                isAuthenticated: false
            }
        case USER_LOADED_SUCCESS:
            return {
                ...state,
                user: payload,
                
            }
        case AUTHENTICATED_FAIL:
            return {
                ...state,
                isAuthenticated: false,
                isLoading: false,
            }
        case USER_LOADED_FAIL:
            return {
                ...state,
                user: null,
               
            }
        case LOGIN_FAIL:
        case SIGNUP_FAIL:
        case LOGOUT:
            localStorage.removeItem('access');
            localStorage.removeItem('refresh');
            return {
                ...state,
                access: null,
                refresh: null,
                isAuthenticated: false,
                user: null
            }
        case PASSWORD_RESET_SUCCESS:
        case PASSWORD_RESET_FAIL:
        case PASSWORD_RESET_CONFIRM_SUCCESS:
        case PASSWORD_RESET_CONFIRM_FAIL:
        case ACTIVATION_SUCCESS:
        case ACTIVATION_FAIL:
            return {
                ...state
            }
        default:
            return state
    }
};

这是 actions/auth 文件的认证部分。在这个文件中,我首先发送 AUTHENTICATED_LOADING 变量,以确保在开始检查身份验证时 isLoading = true。

export const checkAuthenticated = () => async dispatch => {
    dispatch({ type: AUTHENTICATED_LOADING });
    if (localStorage.getItem('access')) {
        const config = {
            headers: {
                'Content-Type': 'application/json',
                'Accept': 'application/json'
            }
        }; 

        const body = JSON.stringify({ token: localStorage.getItem('access') });

        try {
            
            const res = await axios.post(`/auth/jwt/verify/`, body, config)

            if (res.data.code !== 'token_not_valid') {
                dispatch({
                    type: AUTHENTICATED_SUCCESS
                });
            } else {
                dispatch({
                    type: AUTHENTICATED_FAIL
                });
            }
        } catch (err) {
            dispatch({
                type: AUTHENTICATED_FAIL
            });
        }

    } else {
        dispatch({
            type: AUTHENTICATED_FAIL
        });
    }
};

0 个答案:

没有答案