在 React 中,如何在身份验证之后但在授权之前从数据库中检索信息?



我正在构建一个链接到Firebase Auth的React应用程序。 我按照本教程进行了设置。

因此,我现在有一个应用程序,允许用户通过在提交登录表单时执行以下操作来登录:

onSubmit = event => {
const { email, password } = this.state;
this.props.firebase
.doSignInWithEmailAndPassword(email, password)
.then(
this.setState({ ...INITIAL_STATE }),
this.props.history.push(ROUTES.DASHBOARD)
)
.catch(error => {
this.setState({ error });
});
event.preventDefault();
};

仪表板通过包装授权组件进行保护:

const condition = authUser => !!authUser;
export default withAuthorization(condition)(DashboardPage));

因此,主应用索引.js为:

const App = () => (
<Router>
<Switch>
<Route exact path='/'  render={(props) => <LandingPage {...props} />}/>
<Route exact path={ROUTES.LANDING}  render={(props) => <LandingPage {...props} />}/>
<Route exact path={ROUTES.DASHBOARD}  render={(props) => <Dashboard {...props} />}/>
...
</Switch>
</Router>
);
export default withAuthentication(App);

因此,最初向用户显示没有授权的登录页面。 登录后,用户将重定向到仪表板,这需要授权。

目前,授权只是"用户是否登录?",这很好。因此,用户登录并(成功时(将重定向到仪表板,我们在其中检查他们是否已登录,然后显示页面。

但是,我希望授权更具体。 我有不同类型的用户 - 假设管理员和非管理员。 只有管理员才能看到"仪表板"页面。此信息(无论用户是否为管理员(保存在我自己的数据库中,而不是保存在 Firebase 身份验证数据库中(我无法更改此设置(。 因此,我需要能够执行以下操作:

  • 当用户点击"提交"时对用户进行身份验证 - 这将仅使用设置的电子邮件地址创建"authUser">
  • 然后检索其他信息(isAdmin(并将其添加到authUser
  • 然后重定向到仪表板

我不知道如何在检索附加信息的中间步骤中插入。 如果我将其作为"onSubmit"处理的一部分(因此在检索身份验证用户之后但在重定向和触发授权之前(,我无法在 authUser 中设置它。 如果我在身份验证中执行此操作,则在进行数据库调用之前调用授权,因此它会失败。

我想我需要某种回调,以便我对用户进行身份验证,然后我只能在提取数据后触发重定向,而不是从onSubmit重定向。因此,身份验证成功> authUser 仅填充电子邮件>进行数据库调用,并且找到管理员状态>然后重定向到仪表板。 但是我无法从身份验证中重定向,因为它不在路由器中。

您可以通过将它们一个嵌套在前一个调用的 callack 中来链接顺序异步调用(不过要小心回调地狱(。

onSubmit方法中,可以对其他数据库进行 AJAX 调用(我们将其称为OtherDB(,以检索有关成功登录用户的额外信息。在最后一个调用的回调中,您有关于用户的额外信息,您可以使用这些信息来决定将用户重定向到何处(如果有的话(。

以下是有关代码外观的粗略想法:

onSubmit = (event) => {
const { email, password } = this.state;
this.props.firebase.doSignInWithEmailAndPassword(email, password)
.then(() => {
OtherDB.whatKindOfUserIsThis(email)
.then((userType) => {
if (userType === 'Admin') {
this.setState({ ...INITIAL_STATE });
this.props.history.push(ROUTES.DASHBOARD);
}
else {
console.log('Nope');
}
})
.catch(error => {
this.setState({ error });
});
})
.catch(error => {
this.setState({ error });
});
event.preventDefault();
};

这种代码形状应该可以解决问题,显然,这假设您在 UI 代码中引用了另一个数据库,并且它具有这样一个方法,该方法使用有关给定用户的信息进行响应。

建议:这可能是一个不正确的假设,但查看您现在拥有的代码,我注意到您的路由不受保护,从某种意义上说,如果用户在成功登录后直接在浏览器中输入仪表板 URL,即使您使用我上面粘贴的代码,他们都会被重定向到那里无论其类型如何。我假设您需要在Authorization组件中添加额外的保护,不仅要检查用户是否已登录,还要检查其类型。

最新更新