React router react router redux如何更新页面加载状态以进行身份验证

React router react router redux如何更新页面加载状态以进行身份验证,react-router,redux,React Router,Redux,我将其用作初学者工具包,并尝试将身份验证引入初学者应用程序 我的身份验证正在工作,它设置了状态。登录成功后,我在受保护的路由上有一个onEnter,它调用isAuthenticated()来检查用户是否经过身份验证 这就是我迷路的地方,我不知道如何检查state.auth.user和localStorage.token以确保设置了内容 在我看来,我需要解释两个案例 用户已登录,但随后刷新了页面。这意味着令牌仍在本地存储中,但状态已被擦除,因此我需要通过解码令牌并将其重新注入到state.auth

我将其用作初学者工具包,并尝试将身份验证引入初学者应用程序

我的身份验证正在工作,它设置了
状态。登录成功后,我在受保护的路由上有一个
onEnter
,它调用
isAuthenticated()
来检查用户是否经过身份验证

这就是我迷路的地方,我不知道如何检查
state.auth.user
localStorage.token
以确保设置了内容

在我看来,我需要解释两个案例

  • 用户已登录,但随后刷新了页面。这意味着令牌仍在本地存储中,但状态已被擦除,因此我需要通过解码令牌并将其重新注入到
    state.auth.user
  • 如果用户未登录,请将其重定向到路由
    /auth/login
    (此部分我已完成)
  • 我的问题是使用初学者工具包时,我不知道如何正确地进入路由文件中的状态/存储,以便检查该
    state.auth.user
    属性。。或者如果这是正确的方法(也许我应该用动作代替)

    redux/modules/auth.js

    import { createAction, handleActions } from 'redux-actions';
    import { pushPath } from 'redux-simple-router'
    // ------------------------------------
    // Constants
    // ------------------------------------
    export const LOGIN_REQUEST = 'LOGIN_REQUEST';
    export const LOGIN_SUCCESS = 'LOGIN_SUCCESS';
    export const LOGIN_FAILURE = 'LOGIN_FAILURE';
    export const STORE_USER = 'STORE_USER';
    export const IS_AUTHENTICATED = 'IS_AUTHENTICATED';
    
    const initialState = {
      isFetching: false,
      isAuthenticated: false,
      user: {},
      token: ''
    };
    
    // ------------------------------------
    // Actions
    // ------------------------------------
    export const requestLogin = createAction(LOGIN_REQUEST, (payload) => payload);
    export const receiveLogin = createAction(LOGIN_SUCCESS, (payload) => payload);
    export const invalidLogin = createAction(LOGIN_FAILURE, (payload) => payload);
    
    export const isAuthenticated = () => {
      return !!getToken();
    };
    
    const getToken = () => {
      return localStorage.token;
    };
    
    const _decodeToken = (token) => {
      return window.atob(token.split('.')[1]);
    };
    
    const storeToken = (token) => {
      localStorage.token = token;
    };
    
    export const doLogin = (identity, password) => {
      return (dispatch, getState) => {
        dispatch(requestLogin({ identity, password }));
        // mock backend call
        setTimeout(function () {
          var token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZmlyc3ROYW1lIjoiQWRtaW4iLCJsYXN0TmFtZSI6ImlzdHJhdG9yIiwiZW1haWwiOiJhZG1pbkBhenN1cHJhcy5jb20iLCJjcmVhdGVkQXQiOiIyMDE1LTEyLTMwVDIxOjMyOjIxLjM1NloiLCJ1cGRhdGVkQXQiOiIyMDE1LTEyLTMwVDIxOjMzOjE3LjQzMloiLCJpZCI6IjU2ODQ0ZDY1Y2UzMjEyZTUwMWE3ZmNmNyIsImlhdCI6MTQ1MTUxNjU5N30.qpDmsnpMaHZy4QITS5IBPhPieNER7QHKSFWzsvulWC8';
          storeToken(token);
          dispatch(receiveLogin({ user: { username: 'admin', uid: 1 }, token }));
          dispatch(pushPath('/'));
        }, 3000);
      };
    };
    
    export const actions = {
      doLogin,
      isAuthenticated
    };
    
    // ------------------------------------
    // Reducer
    // ------------------------------------
    export default handleActions({
      [LOGIN_REQUEST]: (state, { payload }) => {
        return {
          ...state,
          isFetching: true,
          isAuthenticated: false
        };
      },
      [LOGIN_SUCCESS]: (state, { payload }) => {
        return {
          ...state,
          isFetching: false,
          isAuthenticated: true,
          token: payload.token,
          user: payload.user
        };
      },
      [LOGIN_FAILURE]: (state, { payload }) => {
        return {
          ...state,
          isFetching: false,
          isAuthenticated: false,
          message: payload
        };
      }
    }, initialState);
    
    import { Route, IndexRoute } from 'react-router';
    
    // NOTE: here we're making use of the `resolve.root` configuration
    // option in webpack, which allows us to specify import paths as if
    // they were from the root of the ~/src directory. This makes it
    // very easy to navigate to files regardless of how deeply nested
    // your current file is.
    import CoreLayout from 'layouts/CoreLayout';
    import AuthLayout from 'layouts/AuthLayout';
    
    import HomeView from 'views/HomeView';
    import LoginView from 'views/auth/LoginView';
    
    import { actions as authActions } from '../redux/modules/auth';
    
    function isAuthenticated (nextState, replaceState) {
      if (authActions.isAuthenticated()) {
        replaceState({ nextPathname: nextState.location.pathname }, '/auth/login');
      }
    }
    
    export default (<Route>
      <Route path='/' component={CoreLayout} onEnter={isAuthenticated}>
        <IndexRoute component={HomeView} />
        <Route path='/panel' name='Panel' component={HomeView} />
      </Route>
      <Route path='/auth' component={AuthLayout}>
        <Route path='login' component={LoginView} />
      </Route>
    </Route>);
    
    routes/index.js

    import { createAction, handleActions } from 'redux-actions';
    import { pushPath } from 'redux-simple-router'
    // ------------------------------------
    // Constants
    // ------------------------------------
    export const LOGIN_REQUEST = 'LOGIN_REQUEST';
    export const LOGIN_SUCCESS = 'LOGIN_SUCCESS';
    export const LOGIN_FAILURE = 'LOGIN_FAILURE';
    export const STORE_USER = 'STORE_USER';
    export const IS_AUTHENTICATED = 'IS_AUTHENTICATED';
    
    const initialState = {
      isFetching: false,
      isAuthenticated: false,
      user: {},
      token: ''
    };
    
    // ------------------------------------
    // Actions
    // ------------------------------------
    export const requestLogin = createAction(LOGIN_REQUEST, (payload) => payload);
    export const receiveLogin = createAction(LOGIN_SUCCESS, (payload) => payload);
    export const invalidLogin = createAction(LOGIN_FAILURE, (payload) => payload);
    
    export const isAuthenticated = () => {
      return !!getToken();
    };
    
    const getToken = () => {
      return localStorage.token;
    };
    
    const _decodeToken = (token) => {
      return window.atob(token.split('.')[1]);
    };
    
    const storeToken = (token) => {
      localStorage.token = token;
    };
    
    export const doLogin = (identity, password) => {
      return (dispatch, getState) => {
        dispatch(requestLogin({ identity, password }));
        // mock backend call
        setTimeout(function () {
          var token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZmlyc3ROYW1lIjoiQWRtaW4iLCJsYXN0TmFtZSI6ImlzdHJhdG9yIiwiZW1haWwiOiJhZG1pbkBhenN1cHJhcy5jb20iLCJjcmVhdGVkQXQiOiIyMDE1LTEyLTMwVDIxOjMyOjIxLjM1NloiLCJ1cGRhdGVkQXQiOiIyMDE1LTEyLTMwVDIxOjMzOjE3LjQzMloiLCJpZCI6IjU2ODQ0ZDY1Y2UzMjEyZTUwMWE3ZmNmNyIsImlhdCI6MTQ1MTUxNjU5N30.qpDmsnpMaHZy4QITS5IBPhPieNER7QHKSFWzsvulWC8';
          storeToken(token);
          dispatch(receiveLogin({ user: { username: 'admin', uid: 1 }, token }));
          dispatch(pushPath('/'));
        }, 3000);
      };
    };
    
    export const actions = {
      doLogin,
      isAuthenticated
    };
    
    // ------------------------------------
    // Reducer
    // ------------------------------------
    export default handleActions({
      [LOGIN_REQUEST]: (state, { payload }) => {
        return {
          ...state,
          isFetching: true,
          isAuthenticated: false
        };
      },
      [LOGIN_SUCCESS]: (state, { payload }) => {
        return {
          ...state,
          isFetching: false,
          isAuthenticated: true,
          token: payload.token,
          user: payload.user
        };
      },
      [LOGIN_FAILURE]: (state, { payload }) => {
        return {
          ...state,
          isFetching: false,
          isAuthenticated: false,
          message: payload
        };
      }
    }, initialState);
    
    import { Route, IndexRoute } from 'react-router';
    
    // NOTE: here we're making use of the `resolve.root` configuration
    // option in webpack, which allows us to specify import paths as if
    // they were from the root of the ~/src directory. This makes it
    // very easy to navigate to files regardless of how deeply nested
    // your current file is.
    import CoreLayout from 'layouts/CoreLayout';
    import AuthLayout from 'layouts/AuthLayout';
    
    import HomeView from 'views/HomeView';
    import LoginView from 'views/auth/LoginView';
    
    import { actions as authActions } from '../redux/modules/auth';
    
    function isAuthenticated (nextState, replaceState) {
      if (authActions.isAuthenticated()) {
        replaceState({ nextPathname: nextState.location.pathname }, '/auth/login');
      }
    }
    
    export default (<Route>
      <Route path='/' component={CoreLayout} onEnter={isAuthenticated}>
        <IndexRoute component={HomeView} />
        <Route path='/panel' name='Panel' component={HomeView} />
      </Route>
      <Route path='/auth' component={AuthLayout}>
        <Route path='login' component={LoginView} />
      </Route>
    </Route>);
    
    从'react router'导入{Route,IndexRoute};
    //注意:这里我们使用'resolve.root'配置
    //选项,它允许我们指定导入路径,就像
    //它们来自~/src目录的根目录。这就够了
    //无论嵌套有多深,都很容易导航到文件
    //您当前的文件是。
    从“布局/CoreLayout”导入CoreLayout;
    从“布局/AuthLayout”导入AuthLayout;
    从“视图/家庭视图”导入家庭视图;
    从“视图/auth/LoginView”导入LoginView;
    从“../redux/modules/auth”导入{actions as authActions};
    函数已验证(nextState、replaceState){
    if(authActions.isAuthenticated()){
    replaceState({nextPathname:nextState.location.pathname},'/auth/login');
    }
    }
    导出默认值(
    );
    
    我一直在使用此解决方案

  • 创建AuthenticatedComponent

  • 配置路由器组件需要授权:

  • 检查令牌(页面加载):