React Router: убедитесь, что JWT действителен перед рендерингом частного маршрута. - PullRequest
0 голосов
/ 01 февраля 2020

Я хочу реализовать аутентификацию реального мира для приложения React Router. Каждый учебник, который я видел, использует fakeAuth для имитации аутентификации, но на самом деле не реализует аутентификацию в реальном мире. Я пытаюсь на самом деле реализовать аутентификацию. Возможно ли это?

Прямо сейчас я отправляю jwt на сервер, чтобы проверить, является ли он действительным, перед возвратом Component Я хочу сделать - Redirect в Login, если jwt аутентификация не пройдена, или render Dashboard, если это действительный jwt. Проблема в том, что ProtectedRoute return использует redirect до /login до того, как серверная часть return определяет, действителен jwt или нет.

Как можно Я получаю аутентификацию в реальном мире в своем приложении React-Router? Это вообще возможно?

const PrivateRoute = ({ component: Component, ...rest }) => {

  const [auth, setAuth] = useState(false);

  useEffect(() => {}, [auth])

  useEffect(() => {
    // send jwt to API to see if it's valid
    let token = localStorage.getItem("token");
    if (token) {
      fetch("/protected", {
        method: "POST",
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({ token })
      })
      .then((res) => {
        return res.json()
      })
      .then((json) => {
        if (json.success) {
          setAuth(true);
        }
      })
      .catch((err) => {
        setAuth(false);
        localStorage.removeItem("token");
      });
    }

  }, [])

  return (<Route {...rest}
    render={(props) => {
      return auth ? <Component {...props} /> : <Redirect to="/login" />
    }} />)
  }
}

1 Ответ

1 голос
/ 01 февраля 2020

Я бы сказал, что вам нужно состояние между аутентифицированным / недействительным jwt. Я бы использовал другое поле состояния, isTokenValidated (или isLoading):

const PrivateRoute = ({ component: Component, ...rest }) => {

  const [auth, setAuth] = useState(false);
  const [isTokenValidated, setIsTokenValidated] = useState(false);

  useEffect(() => {
    // send jwt to API to see if it's valid
    let token = localStorage.getItem("token");
    if (token) {
      fetch("/protected", {
        method: "POST",
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({ token })
      })
      .then((res) => {
        return res.json()
      })
      .then((json) => {
        if (json.success) {
          setAuth(true);
        }
      })
      .catch((err) => {
        setAuth(false);
        localStorage.removeItem("token");
      })
      .then(() => setIsTokenValidated(true));
    } else {
       setIsTokenValidated(true); // in case there is no token
    }

  }, [])

 if (!isTokenValidated) return <div />; // or some kind of loading animation

  return (<Route {...rest}
    render={(props) => {
      return auth ? <Component {...props} /> : <Redirect to="/login" />
    }} />)
  }
}
...