React 路由身份验证
我们将在 React 应用程序中介绍受保护的路由和使用 react-router 的身份验证。
在 React 中构建商业 Web 应用程序或网站时,我们经常需要对未登录或不具有访问这些路由所需的特定用户角色的用户隐藏应用程序中的某些路由。
React 路由为我们提供了受保护的路由;他们让我们根据用户角色或是否登录来选择用户可以访问的路由。
例如,我们有一个所有用户都可以访问的 home
、about
、contact
和 login
页面。但受保护的路由,如仪表板
和配置文件设置
只能由登录用户访问。
React 路由没有为此提供任何功能,但添加此功能非常简单直接。首先,我们需要添加功能来验证用户以开始处理受保护的路由。
我们将使用假的 AuthUser
Hook 来检查身份验证状态。
让我们使用以下命令创建一个新应用程序。
# react
npx create-react-app my-app
在 React 中创建我们的新应用程序后,我们将使用此命令转到我们的应用程序目录。
# react
cd my-app
现在,让我们运行我们的应用程序来检查所有依赖项是否安装正确。
# react
npm start
我们将在 src
文件夹中创建一个新文件 AuthUser.js
。一旦我们创建了一个新文件,现在我们将创建一个上下文并将其分配给一个常量 authUserContext
。
# react
const authUserContext = React.createContext();
一旦我们创建了一个上下文,现在我们将创建一个函数 AuthUser
,它将两个变量的状态设置为 authenticate
和 setAuthenticate
为 false,我们将使用它来检查用户是否经过身份验证。
我们将创建 2 个方法来返回 login()
和 logout()
。login()
会将 setAuthenticate
的值设置为 true,而 logout()
会将其设置回 false。
现在,我们将导出函数 AuthenticationProvider
,它将 AuthUser()
保存在一个常量 auth
中。所以我们在 AuthUser.js
中的代码将如下所示。
import * as React from "react";
const authUserContext = React.createContext();
function AuthUser() {
const [authenticate, setAuthenticate] = React.useState(false);
return {
authenticate,
login() {
return new Promise((res) => {
setAuthenticate(true);
res();
});
},
logout() {
return new Promise((res) => {
setAuthenticate(false);
res();
});
}
};
}
export function AuthenticationProvider({ children }) {
const auth = AuthUser();
return (
<authUserContext.Provider value={auth}>{children}</authUserContext.Provider>
);
}
export default function AuthenticateConsumer() {
return React.useContext(authUserContext);
}
每当我们想使用 authenticate
、login()
和 logout()
时,我们都可以使用 AuthUser
Hook。我们将开始构建导航,它将包含 5 个组件 Home
、About
、Profile
、Login
、Dashboard
。
Home
、About
和 Login
将是公开访问的,而 Dashboard
和 Profile
只有在用户通过身份验证后才能访问。
首先,我们将从 react-router-dom
导入 Link
、Routes
、Route
、UseNavigate
和 userLocation
。我们还将从我们创建的新文件中导入 AuthUser
。
# react
import * as React from "react";
import {
Link,
Routes,
Route,
useNavigate,
Navigate,
useLocation
} from "react-router-dom";
import AuthUser from "./AuthUser";
现在,我们将为访问某个导航链接时显示的导航定义常量。
如果是可公开访问的链接,则会显示公共路由,如果是私有链接,则只有在用户通过身份验证后才会显示私有路由。否则,它将被重定向到登录页面。
# react
const Home = () => <h1>Home (Public Route)</h1>;
const About = () => <h1>About (Public Route)</h1>;
const Dashboard = () => <h1>Dashboard (Private)</h1>;
const Profile = () => <h1>Profile (Private)</h1>;
现在我们将为 Login
方法创建一个常量,我们将在其中登录用户,并在验证后将其重定向到 dashboard
。
如果用户未登录,它将返回一个登录页面内容,每当未经身份验证的用户尝试访问私有页面时,都会显示该登录页面内容。
const Login = () => {
const navigate = useNavigate();
const { login } = AuthUser();
const { state } = useLocation();
const handleLogin = () => {
login().then(() => {
navigate(state?.path || "/dashboard");
});
};
return (
<div>
<h1>Login</h1>
<button onClick={handleLogin}>Log in</button>
</div>
);
};
现在我们将创建一个导航函数,其中我们将返回一个导航栏,其中包含所有路由,包括公共和私有路由,如果用户未通过身份验证,则带有登录按钮,如果用户通过身份验证,则会显示注销按钮。
我们还将创建 2 个方法,handleLogout
和 handleLogin
。
function Nav() {
const { authenticate, logout, login } = AuthUser();
const navigate = useNavigate();
const handleLogout = () => {
logout();
navigate("/");
};
const handleLogin = () => {
login();
navigate("/dashboard");
};
return (
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/dashboard">Dashboard</Link>
</li>
<li>
<Link to="/profile">Profile</Link>
</li>
<li>{!authenticate && <button onClick={handleLogin}>Login</button>}</li>
</ul>
{authenticate && <button onClick={handleLogout}>Logout</button>}
</nav>
);
}
我们将创建一个函数 RequireAuthentication
,每当用户尝试访问私有路由时,该函数将对用户进行身份验证。
function RequireAuthentication({ children }) {
const { authenticate } = AuthUser();
const location = useLocation();
return authenticate === true ? (
children
) : (
<Navigate to="/login" replace state={{ path: location.pathname }} />
);
}
在我们的 App()
函数中,我们将定义我们的路由。
export default function App() {
return (
<div>
<Nav />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route
path="/dashboard"
element={
<RequireAuthentication>
<Dashboard />
</RequireAuthentication>
}
/>
<Route
path="/profile"
element={
<RequireAuthentication>
<Profile />
</RequireAuthentication>
}
/>
<Route path="/login" element={<Login />} />
</Routes>
</div>
);
}
让我们测试我们的应用程序并检查它是如何工作的。请参阅此处的演示。
输出:
正如你在上面的示例中看到的那样,设置经过身份验证的路由非常容易,但是我们使用的这个 AuthUser
Hook 只是一个前端检查。
但是,如果我们正在开发一个合适的 Web 应用程序,我们需要在后端对用户进行身份验证以保护我们的系统。
相关文章
在 React 中循环遍历对象数组
发布时间:2023/03/18 浏览次数:124 分类:React
-
在 React 中循环对象数组: 使用 map() 方法迭代数组。 我们传递给 map() 的函数会为数组中的每个元素调用。 该方法返回一个新数组,其中包含传入函数的结果。 export default function App (
获取 React 中元素的类名
发布时间:2023/03/18 浏览次数:162 分类:React
-
在 React 中使用 event.target 获取元素的类名 获取元素的类名: 将元素上的 onClick 属性设置为事件处理函数。 访问元素的类名作为 event.currentTarget.className 。 export default function App () { cons
如何将 key 属性添加到 React 片段
发布时间:2023/03/18 浏览次数:152 分类:React
-
使用更详细的片段语法将 key 属性添加到 React 片段,例如 React.Fragment key={key} 。 更冗长的语法实现了相同的结果对元素列表进行分组,而不向 DOM 添加额外的节点。 import React from react
如何在 React 中删除事件监听器
发布时间:2023/03/15 浏览次数:203 分类:React
-
在 React 中删除事件监听器: 在 useEffect 挂钩中添加事件侦听器。 从 useEffect 挂钩返回一个函数。 当组件卸载时,使用 removeEventListener 方法移除事件监听器。 import {useRef, useEffect} from r
React 中在 map() 中使用条件跳出map
发布时间:2023/03/15 浏览次数:198 分类:React
-
React 中在 map() 中使用条件: 在数组上调用 map() 方法。 使用 if 条件,如果条件满足则显式返回。 否则返回不同的值或返回 null 以不呈现任何内容。 export default function App () { const arr =
在 React 中调用多个 onClick 函数
发布时间:2023/03/15 浏览次数:160 分类:React
-
在 React 中调用多个 onClick 函数: 在元素上设置 onClick 属性。 在事件处理函数中调用其他函数。 事件处理函数可以根据需要调用尽可能多的其他函数。 export default function App () { const s
在 React 中按类名查找所有元素
发布时间:2023/03/15 浏览次数:171 分类:React
-
在 React 中通过 className 查找所有元素: 使用 getElementsByClassName 方法获取具有特定类的所有元素。 将对该方法的调用放在 useEffect() 钩子中。 import {useEffect} from react ; const App = () = { useEf
在 React 中检查元素是否获取到焦点
发布时间:2023/03/15 浏览次数:154 分类:React
-
要检查元素是否在 React 中获得焦点: 在元素上设置 ref 属性。 元素呈现后,检查元素是否是文档中的活动元素。 如果是,则该元素被聚焦。 import {useEffect, useRef} from react ; export defaul
在 React 中悬停时显示元素或文本
发布时间:2023/03/13 浏览次数:160 分类:React
-
在 React 中悬停时显示元素或文本: 在元素上设置 onMouseOver 和 onMouseOut 属性。 跟踪用户是否将鼠标悬停在状态变量中的元素上。 根据状态变量有条件地渲染另一个元素。 import {useStat