Как я могу обновить состояние при загрузке страницы для аутентификации

Я использую https://github.com/davezuko/react-redux-starter-kit в качестве стартового набора и пытаюсь ввести аутентификацию в стартовом приложении.

У меня аутентификация работает, она устанавливает state.auth при успешном входе в систему, у меня есть onEnter на моих защищенных маршрутах, которые звонки isAuthenticated() проверить, аутентифицирован ли пользователь.

Это где я теряюсь, и я не уверен, как проверить оба state.auth.user и localStorage.token чтобы убедиться, что все установлено.

Как я понимаю, мне нужно учитывать два случая

  1. пользователь вошел в систему, но затем обновил страницу. Это означает, что токен все еще находится в localStorage, но состояние удалено, поэтому мне нужно перезагрузить состояние, расшифровав токен и повторно вставив его в state.auth.user
  2. пользователь не авторизован, перенаправьте его на маршрут /auth/login (эта часть у меня работает).

Моя проблема в использовании стартового комплекта, я не знаю, как правильно добраться до состояния / магазина в моем файле маршрутов, чтобы я мог проверить это state.auth.user собственность.. или если это даже правильный способ сделать это (возможно, я должен использовать действие вместо этого)?

Redux/ модули /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>);

1 ответ

Решение

Я использовал это решение с https://github.com/davezuko/react-redux-starter-kit

  1. Создание AuthenticatedComponent https://github.com/joshgeller/react-redux-jwt-auth-example/blob/master/src/components/AuthenticatedComponent.js

  2. Для настройки маршрутизатора требуется авторизация: https://github.com/joshgeller/react-redux-jwt-auth-example/blob/master/src/routes/index.js

  3. Проверить токен (загрузка страницы): https://github.com/joshgeller/react-redux-jwt-auth-example/blob/master/src/index.js

Другие вопросы по тегам