Безопасная структура аутентификации в React Webapp - PullRequest
0 голосов
/ 28 мая 2020

В настоящее время я изучаю React и проработал несколько курсов, но до сих пор не совсем понял, как создать правильную структуру для безопасного веб-приложения.

Для входа в систему, процесса регистрации я использую firebase SDK. После входа в систему пользователь перенаправляется на частный маршрут. Сейчас у меня всего 2 роли пользователя. Гости и вошли в систему Пользователи. Это позволяет мне создавать частные маршруты с помощью встроенной функции firebase. Это первая проблема, поскольку она не масштабируется, когда я добавляю разные роли, так как это вынудило бы меня отправить запрос в бэкэнд, чтобы проверить, какую роль играет пользователь и, следовательно, к каким страницам он может получить доступ.

if (firebase.auth().currentUser === null) {
        console.log("not logged in")
        return     (<Redirect
            to={{
              pathname: "/signin",
              state: {
                from: props.location
              }
            }}
          />);

    }

Поэтому я подумал, что самым простым вариантом было бы использовать Context, который действительно работал. После того, как пользователь входит в систему, сервер отправляет объект пользователя, на который приложение ссылается до конца сеанса. Я следил за кучей руководств, и все они имели ту же проблему, что при использовании инструментов разработчика chrome с функциями реагирования вы могли просто отредактировать состояние пользователя и обойти частные маршруты et c.

Вторая попытка:

<UserContext.Consumer>{(context)=>{
          const {isLoggedIn} = context
          return(
        <Route
          {...rest}
          render={props => {

        if (isLoggedIn) {
            console.log("not logged in")
            return     (<Redirect
                to={{
                  pathname: "/signin",
                  state: {
                    from: props.location
                  }
                }}
              />);

Я был бы признателен, если бы кто-нибудь мог указать мне направление, поскольку мне кажется, что я упускаю что-то важное.

РЕДАКТИРОВАТЬ 1: Или это просто как только вы создадите приложение, вы больше не сможете получить доступ к этим состояниям, и это считается безопасным?

Ответы [ 2 ]

0 голосов
/ 29 мая 2020

Я думаю, что то, что вы делаете на веб-сайте, хорошо, но вам также понадобится logi c на сервере для защиты ваших маршрутов. Это означает, что пользователь может обойти вашу защиту маршрута с помощью инструментов разработки на интерфейсе, но ваш бэкэнд будет отправлять ему только сообщения об ошибках, поскольку он признает, что у него нет разрешения.

Вы могли бы это сделать. с такими функциями высшего порядка, как эта:

const authenticationWrapper = createResolver(
  async ( models, session, SALT ) => {
    try {
      if (!session) {
        throw new Error("No valid credentials!");
      }

      const { id } = verify(session.token, salt);

      const valid = databasecall //

      if (!valid) {
        throw new Error("No valid user!");
      }

      return true
    } catch (error) {
      session.destroy((err) => {
        if (err) {
          console.error(err);
        }
      });
    }
  }
);

Все частные внутренние функции будут обернуты, и аутентификация пользователя будет проверяться каждый раз.

Принцип проверки во Front- и Backend называется двойной аутентификацией. Подробнее об этом можно прочитать здесь .

0 голосов
/ 29 мая 2020

при использовании chrome инструментов разработчика с функциями реагирования вы можете просто отредактировать состояние пользователя и обойти частные маршруты

Ваши маршруты никогда не будут по-настоящему частными. Они являются частью пакета JavaScript, который загружается и отображается браузером, поэтому они никогда не должны содержать ничего секретного. Кто угодно мог прочитать этот код, если бы действительно захотел.

Учтите это:

if (loggedIn) {
  return <div>Secret data: ABC</div>;
}

Строка «AB C» содержится в сборке вашего приложения и на самом деле не является секретом больше. Обычный пользователь не знает, как его получить, но разработчик, вероятно, мог бы, например, переключить какое-либо состояние в консоли разработчика.

Однако данные, поступающие из Firestore (или любой другой серверной службы) должны быть должным образом защищены. Проверки разрешений выполняются на стороне сервера перед отправкой этих данных в браузер. Таким образом, если у пользователя нет необходимых разрешений, данные никогда не будут открыты не тому человеку, даже если кто-то вмешается в ваш клиентский код в консоли разработчика.

if (loggedIn) {
  fetchDataFromBackend();
}

Это не имеет значения если кто-то изменит loggedIn на true, чтобы вызвать fetchDataFromBackend(); сервер будет следить за тем, чтобы данные не возвращались, если у пользователя нет соответствующих разрешений (например, он вошел в систему). В случае Firebase (Firestore) эта защита достигается с помощью правил безопасности.

И, кстати, рекомендуемый способ получить текущего пользователя с помощью Firebase - это добавить слушателя. в объект Auth:

firebase.auth().onAuthStateChanged(function(user) {
  if (user) {
    // User is signed in.
  } else {
    // No user is signed in.
  }
});

Вы можете поместить это в компонент верхнего уровня и поделиться объектом user с дочерними компонентами через контекст. Таким образом, вам не придется звонить по номеру firebase.auth() по всему миру. Вот хорошая отправная точка, если вам нужно вдохновение: https://usehooks.com/useAuth/

...