【问题标题】:How to authenticate with Routes in React.js如何使用 React.js 中的路由进行身份验证
【发布时间】:2021-11-18 11:17:50
【问题描述】:

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

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

错误文本:

错误:对象作为 React 子对象无效(找到:[object 承诺])。如果您打算渲染一组孩子,请使用 代替数组。

在用户访问某个地址之前,我必须通过服务器验证该用户,因为用户使用该站点有时间限制,所以我使用了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>
    );
}

【问题讨论】:

    标签: reactjs authentication routes react-router jsx


    【解决方案1】:

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

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

    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>
    

    我还在此代码沙箱中创建了受保护的身份验证路由以供参考: https://codesandbox.io/s/cranky-poincare-l2c06?file=/src/App.js:262-488

    【讨论】:

    • 并不复杂。我在任何想要运行的页面之前对用户进行身份验证,因为用户有使用该站点的时间限制,因此应该在每个页面上检查他的时间。如果代码有看不懂的地方,发消息解释一下。
    【解决方案2】:

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

    私人页面

    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 },
              }}
            />
          );
        }}
      />
    );

    基本页面

    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 },
                    }}
                />
            );
        }}
    />
    )

    【讨论】:

    • 位置被添加到状态以防万一您在当前路线中有任何查询参数并希望继续使用。
    • 不工作,给出的错误:Objects are not valid as a React child (found: [object Promise])。如果您打算渲染一组子项,请改用数组。
    • 您是否在没有Switch 或任何容器的情况下传递Routes 的列表? PrivatePage 需要独生子女。
    • 我有几个PrivatePages,我又更新了帖子,你能解决问题吗?
    • 能否请您使用我创建的组件并更新示例?我已经更新了 BasePage 和 PrivatePage 组件。
    【解决方案3】:
    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.SGP_PORTAL_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>
        );
    }
    

    【讨论】:

      猜你喜欢
      • 2017-05-05
      • 2021-01-22
      • 1970-01-01
      • 2018-12-27
      • 2019-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-28
      相关资源
      最近更新 更多