Как реализовать грамотную проверку авторизации?

Есть три компонента: SignIn, Home, Account. После удачной авторизации в компоненте SignIn, в Redux хранилище имеются данные пользователя. Как организовать грамотную переадресацию в случаях:
Если пользователь зашел на страницу Account без авторизации, его перебросит на SignIn и наоборот же, в случае авторизации при переходе на SignIn перенаправляет на Home.

Сервер создает сессию и она хранит данные пользователя.
Как со всем этим работать? Если ли примеры? Подскажите.
  • Вопрос задан
  • 1252 просмотра
Решения вопроса 1
maxfarseer
@maxfarseer
https://maxpfrontend.ru, обучаю реакту и компании
Вы используете react-router? Если да, то тут все просто:
1) роуты создаются с помощью функции, таким образом вы можете прокинуть в роутинг store
...
import configRoutes from '../../routes'
...
render() {
  return (
    <Provider store={store}>
      <Router history={routerHistory}>
        {configRoutes(store)}
      </Router>
    </Provider>
  )
}


2) Далее в роутинге, устанавливаете на "защищенные" компоненты onEnter hook:
...
<Route path='/secret-area' component={SecretAreaContainer} onEnter={_ensureAuthenticated}>
...


3) сама функция, смотрит есть ли в store необходимые данные:
export default function configRoutes(store) {
  function _ensureAuthenticated(nextState, replace, callback) {
    const { dispatch } = store
    const { session } = store.getState()
    const { currentUser } = session // данные по юзеру
    let nextUrl

    if (!currentUser && localStorage.getItem('token')) {
        dispatch(getCurrentAccount())
      }
    } else if (!localStorage.getItem('token')) {
      nextUrl = location.pathname + location.search.replace('?', '&')
      replace('/signin')
    }

    callback()
  }

  // здесь ваши роуты


Ок, по роутам готово.

Теперь, по переадресации:
- на success в логине, делаете редирект куда угодно:
export function signIn(email, password) {
  return (dispatch, getState) => {

    dispatch({
      type: USER_SIGN_IN_REQUEST,
    })

    const params = {
      email,
      password,
    }

    httpPost(`${API_ROOT_V1}/api/authenticate`, params)
      .then((data) => {
        saveParamsToLS(data) // здесь токен можно сохранить, например
        dispatch(push('/account')) // ваш РЕДИРЕКТ, используется push из react-router-redux (что необязательно)
      })
      .catch((error) => {
        console.warn(`Sign in error: ${JSON.stringify(error)}`) //eslint-disable-line no-console
        dispatch({
          type: USER_SIGN_IN_FAILURE,
          error: error,
        })
      })
  }
}


и остается кейс с прямым заходом: вы должны разрулить это опять же в onEnter хуке в роутере. Так как у вас есть store, и вам доступны все данные из него, включая store.dispatch метод, добить пример не составит труда.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@davidnum95
Можно использовать для этого HOC. Примерная реализация:
export default function(ComposedComponent) {
  class Authenticate extends React.Component {

    componentWillMount() {
      if (!localStorage.jwtToken) {
        this.context.router.push('/auth');
      }

    }

    componentWillUpdate(nextProps, nextState) {
      if (!nextProps.isAuthenticated) {
        this.context.router.push('/auth');
      }
    }

    render() {
      return (
        <ComposedComponent {...this.props} />
      );
    }
  }

  Authenticate.propTypes = {
    isAuthenticated: React.PropTypes.bool.isRequired,
  };

  Authenticate.contextTypes = {
    router: React.PropTypes.object.isRequired,
  };

  function mapStateToProps(state) {
    return {
      isAuthenticated: state.auth.isAuthenticated,
    };
  };

  return connect(mapStateToProps, { })(Authenticate);

}

В роутере:
<Route path="/main" component={requireAuth(MainPage)} />
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы