javascript - React Protected Routes API 调用
问题描述
我有一个 React 受保护的路由组件,它包裹着我的路由以启用对它们的身份验证。受保护的路由调用 API 端点来检查存储在 HTTP Only cookie 中的 JWT 是否有效。如果是,则呈现与请求的路由关联的组件,如果不是,则返回登录页面。
import React, { useState, useContext } from 'react';
import { Route, Redirect } from 'react-router-dom';
import axios from 'axios';
import { UserContext } from '../functions/UserContext';
const ProtectedRoute = ({ component: Component, ...rest }) => {
const [isAuthenticated, setIsAuthenticated] = useState(0);
const [gotResponse, setGotResponse] = useState(0);
const { user, setUser } = useContext(UserContext);
axios
.post(
process.env.REACT_APP_API_URL + '/api/auth/checkauth/',
{ content: 'checkAuthStatus' },
{
headers: { 'Content-Type': 'application/json' },
withCredentials: true,
}
)
.then((res) => {
setUser(res.data.firstName + ' ' + res.data.lastName);
setIsAuthenticated(1);
setGotResponse(1);
})
.catch(function (error) {
setIsAuthenticated(0);
setGotResponse(1);
});
if (gotResponse === 1) {
return (
<Route
{...rest}
render={(props) => {
if (isAuthenticated === 1) {
return <Component {...rest} {...props} />;
} else {
return (
<Redirect
to={{
pathname: '/login',
state: {
from: props.location,
},
}}
/>
);
}
}}
/>
);
} else {
return null;
}
};
export default ProtectedRoute;
我的大部分路由发生的主要 app.js 文件如下所示;
function App() {
const [user, setUser] = useState();
return (
<main>
<Switch>
<UserContext.Provider value={{ user, setUser }}>
<Route
exact
path="/login"
render={(props) => <Login {...props} />}
></Route>
<ProtectedRoute
exact
path="/account"
component={Account}
title="Account"
></ProtectedRoute>
<ProtectedRoute
exact
path="/staff"
component={Staff}
></ProtectedRoute>
<ProtectedRoute
exact
path="/security"
component={Security}
></ProtectedRoute>
<ProtectedRoute exact path="/" component={Home}></ProtectedRoute>
<Route exact path="/2fa" component={Tfa}></Route>
</UserContext.Provider>
<Route component={NotFound}></Route>
</Switch>
</main>
);
}
export default App;
当应用程序正在运行并且我加载登录页面或任何其他受保护的路由时,我看到对 checkauth API 端点的许多相同请求。 Chrome 网络选项卡屏幕截图
这是因为 React 将我的所有路由加载到一个块中,因此在每个页面加载时为每个路由调用 checkauth 端点?我有点难过。
TIA
解决方案
感谢sojin的提示。我将 api 调用逻辑移动到我的主应用程序函数中,如下所示;
function App() {
const [user, setUser] = useState();
const [authentication, setAuthentication] = useState({
authenticated: false,
initializing: true,
});
useEffect(() => {
axios
.post(
process.env.REACT_APP_API_URL + '/api/auth/checkauth/',
{ content: 'checkAuthStatus' },
{
headers: { 'Content-Type': 'application/json' },
withCredentials: true,
}
)
.then((res) => {
setUser(res.data.firstName + ' ' + res.data.lastName);
setAuthentication({
authenticated: true,
initializing: false,
});
})
.catch(function (error) {
setAuthentication({
authenticated: false,
initializing: false,
});
});
}, [setAuthentication]);
if (authentication.initializing) {
return <div>Loading</div>;
}
return (
<main>
<React.StrictMode>
<Switch>
<UserContext.Provider value={{ user, setUser }}>
<Route
exact
path="/login"
render={(props) => <Login {...props} />}
></Route>
<ProtectedRoute
exact
path="/account"
component={Account}
title="Account"
authenticated={authentication.authenticated}
></ProtectedRoute>
<Route exact path="/staff" component={Staff}></Route>
<ProtectedRoute
exact
path="/security"
component={Security}
authenticated={authentication.authenticated}
></ProtectedRoute>
<ProtectedRoute
exact
path="/"
component={Home}
authenticated={authentication.authenticated}
></ProtectedRoute>
<Route exact path="/2fa" component={Tfa}></Route>
</UserContext.Provider>
<Route component={NotFound}></Route>
</Switch>
</React.StrictMode>
</main>
);
}
export default App;
并像这样调整受保护的路线;
const ProtectedRoute = ({ component: Component, authenticated, ...rest }) => {
return (
<Route
{...rest}
render={(props) => {
if (authenticated) {
return <Component {...rest} {...props} />;
} else {
return (
<Redirect
to={{
pathname: '/login',
state: {
from: props.location,
},
}}
/>
);
}
}}
/>
);
};
export default ProtectedRoute;
我现在只看到在每个页面加载时都按预期命中了 checkauth 端点的单个实例。非常感谢!
推荐阅读
- android - 清除exoplayer的缓存
- java - 如何使用普通 For 循环打印动态数组
- c# - 如何在 .NET Framework 3.5 上使用 System.Threading.Tasks 类
- indexing - 如何在狮身人面像中索引特殊字符
- curl - 如何将 Jenkins 证书凭证绑定用于 curl 请求?
- drupal-8 - 如何增强 Drupal 8 Views 批量操作确认页面?
- java - VS Code 调试无法从 import 语句中解析类,而使用命令行可以正常工作
- python - 在字符串中找到某个字符串
- laravel - 用于自引用表的 web.php 中的 laravel 路由
- reactjs - 如何在 react-native 中访问导航对象