如何使用 React.js 中的路由进行身份验证

How to authenticate with Routes in React.js

我使用这种方法向用户显示私有页面。问题是没有页面显示给我,但我放入 PrivatePage 的日志工作正常。

Components 正确的,因为当我简单地调用路由时,组件被正确返回 但它与 PrivatePage 有问题并且什么都不做。

错误文本:

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.

我必须在用户访问某个地址之前通过服务器验证该用户,因为用户使用该站点有时间限制,所以我使用了Promise

function Auth() {
    return new Promise((resolve, reject) => {
        let appData = GetAppData();
        if (appData.UserToken.length == 0) {
            reject(-2);
        }

    let request = {
        Token: appData.UserToken,
        UserId: appData.UserId
    }

    axios.post("****UserValidUrl****", request).then(response => {
        switch (response.data.Type) {
            case 10:
                resolve(10);
                break;
            case -2:
                reject(-2);
                break;
            case -13:
                reject(-13);
        }
    }).catch(err => {
        reject(-13);
    })
})
}

私人主页:

const PrivatePage = ({children, ...rest}) => (
     return <Route
    {...rest}
    render={async ({location }) => {
        let type = 10;
        try {
            type = await Auth();
        } catch(e) {
            type = -13;
        }

        Log(type);

        switch (type) {
            case 10:
                return children;
                break
            case -2:
                return (
                    <Redirect
                        to={{
                            pathname: '/Auth/Login',
                            state: { from: location },
                        }}
                    />)

            case -13:
                return (
                    <Redirect
                        to={{
                            pathname: '/NotFound',
                            state: { from: location },
                        }}
                    />)
                break;
        }}
    }/>
)

基页:

export default function BasePage() {
    return (
        <div>
            <BrowserRouter>
                <Switch>
                    <Route exact path={"/Auth/Login"} component={Login}/>
                    <PrivatePage path={"/"}>
                        <Switch>
                            <Route exact path={"/"} component={Home}/>
                            <Route exact path={"/Dashboard/Home"} component={Home}/>
                            <Route exact path={"/Dashboard/Profile"} component={Profile}/>
                            <Route component={NotFound}/>
                        </Switch>
                    }/>
                </Switch>
            </BrowserRouter>
        </div>
    );
}

也许你可以在你的私人路线中做这样的事情。

私人主页

const PrivatePage = ({ children, ...rest }) => (
  <Route
    {...rest}
    render={async ({ location }) => {
      let isAuthenticated = false;
      try {
        isAuthenticated = await Auth();
      } catch(e) {
        // If you want to log the error.
      }
    
      if (isAuthenticated) {
        return children;
      }
      return (
        <Redirect
          to={{
            pathname: '/login',
            state: { from: location },
          }}
        />
      );
    }}
  />
);

BasePage

export default function BasePage() {
    return (
        <div>
            <BrowserRouter>
                <Switch>
                    <Route exact path={"/Auth/Login"} component={Login}/>
                    <PrivatePage path={"/"}>
                        <Switch>
                            <Route exact path={"/"} component={Home}/>
                            <Route exact path={"/Dashboard/Home"} component={Home}/>
                            <Route exact path={"/Dashboard/Profile"} component={Profile}/>
                            <Route component={NotFound}/>
                        </Switch>
                    </PrivatePage>
                </Switch>
            </BrowserRouter>
        </div>
    );
}

编辑

PrivatePage 用于 Auth.

中的特定数值

const PrivatePage = ({children, ...rest}) => (
     return <Route
    {...rest}
    render={async ({location }) => {
        let authenticated = false;
        try {
            authenticated = await Auth();
        } catch(e) {
            // If you want to log the error.
        }

        if(authenticated === -2) {
          // redirect one
        } else if (authenticated === -13) {
          // redirect two
        } if (authenticated) {
            return children;
        }

        return (
            <Redirect
                to={{
                    pathname: "/Auth/Login",
                    state: { from: location },
                }}
            />
        );
    }}
/>
)

您的导航看起来很复杂,无法进行身份验证。您可以将您的组件视为路由并像这样进行路由。

假设您已经单独进行了身份验证,并且您只是检查是否可以进行,而不是每次都尝试对路由进行身份验证。如果您更喜欢在路由上进行此身份验证,仍然适用解决方案。

function AuthenticatedRoute({ children, ...props }) {
  const isAuthenticated = useContext(AuthenticationContext);

  return isAuthenticated ? (
    <Route {...props}>{children}</Route>
  ) : (
    <Redirect
      to={{
        pathname: '/login',
        state: { from: location },
      }}
    />
  );
}

并像这样使用它:

<AuthenticatedRoute path="/Dashboard/Home" exact>
  <h1>Hey Doctor Strange! You made it</h1>
</AuthenticatedRoute>

我也在这个代码沙盒中创建了一个protected auth路由供参考: https://codesandbox.io/s/cranky-poincare-l2c06?file=/src/App.js:262-488

export default function PrivateRoute({component: Component, ...props}) {
    let [PAGE_LOADING, SET_PAGE_LOADING] = useState(LOADING_TYPE.Loading);
    let [AUTHENTICATION, SET_AUTHENTICATE] = useState(0);

    useEffect(() => {
        Auth().then((resolve) => {
            SET_AUTHENTICATE(resolve);
        }).catch((reject) => SET_AUTHENTICATE(reject))
            .then(() => SET_PAGE_LOADING(LOADING_TYPE.Default))
    }, [])

    return (
        PAGE_LOADING === LOADING_TYPE.Loading && AUTHENTICATION == 0 ?
            <CtLabel/> :
            <Route
                {...props}
                render={props => (
                    AUTHENTICATION == 10 ?
                        <Component {...props}/> :
                        <Redirect to={ROUTE_PATH.LOGIN}/>
                )}/>
    )
}

而二手:

export default function BasePage() {

    return (
        <BrowserRouter>
            <Switch>
                {/*Other Routes*/}
                <Private path={***} component={Home} exact/>
                <Private path={***} component={Profile} exact/>
                {/*Other Routes*/}
                <Route component={NotFound}/>
            </Switch>
        </BrowserRouter>
    );
}