开发者问题收集

如何使用 react-router-dom amplify 保护或验证 React 路由

2019-12-11
3383

我正在使用 React 和 amplify 构建一个应用程序。身份验证和授权工作正常。但它需要限制用户在登录应用程序之前移动到某些特定的 React 路由。以下代码片段是我尝试过的,如果 isAuthenticated() 返回 false,它就会起作用。但由于我使用 Amplify,所以我使用了一个方法

const PrivateRoute = ({ component: Component, ...rest }) => (
  <Route
    {...rest}
    render={async props =>
      await isAuthenticated() ? (
        <Navigation>
          <Component {...props} />
        </Navigation>
      ) : (
        <Redirect to="/login" />
      )
    }
  />
);

这是我的 isAuthenticated() 函数代码。

import Auth from "@aws-amplify/auth";
export const isAuthenticated = async () => {
  try {
    return await Auth.currentSession().isValid();
  } catch (error) {
    return false;
  }
};

但这会引发这样的错误。

Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.

我知道这是因为它返回了一个承诺,但我在等待它,但它没有工作,我想这有什么原因吗?

2个回答

将您的私有路线组件更改为以下内容:

const PrivateRoute = ({ component: Component, ...rest }) => {
  const [isLoggedIn, setIsLoggedIn] = useState(false)
  useEffect(async () => {
    const isAuth = await isAuthenticated()
    setIsLoggedIn(isAuth)
  }, [])
  return (
    <Route
      {...rest}
      render={props =>
        isLoggedIn ? (
          <Navigation>
            <Component {...props} />
          </Navigation>
        ) : (
            <Redirect to="/login" />
          )
      }
    />
  )
}
Noman Hassan
2019-12-11

我认为处理此问题的更好方法是使用 redux saga,并定义受保护路由数组。

路由器:

function Router() {
    return (
        <Switch>
            <ProtectedRoute exact path="/">
                <Home/>
            </ProtectedRoute>
            <Route path="/login/">
                <Login/>
            </Route>
        </Switch>
    );
}

export default Router;

私有路由:

Auth.configure(awsconfig);

function PrivateRoute({ children, ...rest }) {

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

    const isAuthenticated = () => {

        setAuth(false);

        Auth.currentSession().then( response => {
            if(response.isValid()) {
                setAuth(true);
            } else {
                redirectToLogin();
            }
        }).catch(() => {
            redirectToLogin();
        });
    }

    const redirectToLogin = () => {
        history.push('/login');
    }

    useEffect(() => {
        isAuthenticated();
    }, []);

    return (
        <Route {...rest}>
            { auth ? children : null }
        </Route>
    )
}

export default PrivateRoute;
Stanislau Ladutska
2021-02-11