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

时间:2016-01-06 01:32:05

标签: react-router redux

我正在使用https://github.com/davezuko/react-redux-starter-kit作为初学者工具包并尝试将身份验证引入初学者应用程序。

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

这是我迷路的地方,我不知道如何检查state.auth.userlocalStorage.token以确保设置完成。

我看到的方式,我需要考虑两个案例

  1. 用户已登录,但随后刷新了该页面。这意味着令牌仍然在localStorage中但状态被擦除,因此我需要通过解码令牌并将其重新注入state.auth.user来重新加载状态
  2. 用户未登录,将其重定向到路由/auth/login(此部分我已正常工作)。
  3. 我的问题是使用入门套件我不知道如何正确到我的路线文件中的状态/存储,所以我可以检查state.auth.user属性..或者如果那样甚至是正确的方式(也许我应该使用动作)?

    终极版/模块/ 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);
    

    路由/ index.js

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