如何使用Node.js和React.js防止对管理页面的访问
在许多网站中,最终用户可用的内容是有限的,直到他/她通过登录证明自己的真实性。在MERN堆栈应用程序的开发过程中,当服务器链接到客户端时,我们可能想限制用户访问的页面,除非他已经登录了。在这篇文章中,让我们来看看如何使用React.js和Node.js来限制访问管理页面。
前置条件:
- Functional Components
- React Hooks
- React Router V6
- 基本CRUD操作
客户端需要的模块:
- axios
- react-router-dom
服务器端需要的模块:
- express
- cors
客户端和服务器设置:
第1步:使用命令创建一个npm资源库。
npm init --y
第2步:通过使用命令创建一个新的react客户端项目。
npx create-react-app client
第3步:用命令在当前目录下创建一个服务器文件。
touch server.js
第4步:切换到客户端文件夹中的src文件夹,使用以下命令删除所有文件。
cd client
cd src
rm *
第5步:在src文件夹中创建一个页面文件夹。
mkdir pages
第6步:在src文件夹中创建App.js、index.js和PrivateRoute.js文件。
touch App.js index.js PrivateRoute.js
第7步:在pages文件夹中创建Home.js Admin.js文件。
cd pages
touch Home.js Admin.js
第8步:在客户端文件夹中安装Axios和react-router-dom。
npm i axios react-router-dom
第9步:在服务器端安装Express和cors。
npm i express cors
项目结构:项目中的文件结构将看起来像这样。
Project Structure
第10步:编辑index.js以链接HTML文件和react库。
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
第11步:编辑Home.js,说明一个基本的主页。
const Home = () => {
return(
<div className="home">
<h1>This is the Home page</h1>
</div>
)
}
export default Home;
第12步:编辑Admin.js来说明一个基本的管理页面
const Admin = () => {
return(
<div>
<h1>Admin Page</h1>
</div>
)
}
export default Admin;
第13步:创建一个私人路由,防止未经授权的用户访问网页。这个路由可以用于任何需要保护的组件。私人路由本质上是对服务器进行API调用以检查用户的真实性。如果成功通过验证,该路由就会渲染所谓的组件,否则就会重定向到主页。
// Importing the required libraries
import { Navigate } from "react-router-dom";
import { useEffect, useState } from "react";
const axios = require('axios');
// Private Route Component
// Params: login -> indicates the login state
// children -> the child components of private route
const PrivateRoute = ({ login, children }) => {
// Authentication Handler
const authenticate = (login) => {
setLoading(true);
// HTTP Post Request
axios({
method: 'post',
url: 'http://localhost:8000/admin',
data: {
logged: login,
}
}).then(({ data }) => {
if(data.success){
setAuth(true);
}else{
setAuth(false);
}
console.log(data.message);
setLoading(false);
}).catch((error) => {
console.log(error);
setLoading(false);
})
}
// useState hook to inform the user about the loading state
const [loading, setLoading] = useState(true);
// useState hook to authorize the user
const [auth, setAuth] = useState(false);
// Authenticates the user whenever the
// login state changes
useEffect(() => {
authenticate(login);
return () => {
setLoading(true);
};
}, [login])
// If authenticated loads the required component
// else redirects to the home page
return loading ? (
<h1>Loading...</h1>
) : auth ? children : (
<Navigate to="/" />
);
};
export default PrivateRoute;
第14步:将App.js文件中的所有组件整合起来。路由器被用来在主页和管理页之间导航。我们将创建一个按钮组件来登录和退出创建链接标签是为了导航的目的。本地存储用于在随后的重新登录之间维持登录状态。
// Importing the required modules
import { BrowserRouter as Router, Routes,
Route, Link } from "react-router-dom";
import Home from "./pages/Home";
import Admin from "./pages/Admin";
import PrivateRoute from "./PrivateRoute";
import { useEffect, useState } from "react";
const App = () => {
// useState hook to keep track of the login state
const [login, setLogin] = useState(() => {
// Used local storage to sustain the login state
if(!localStorage.getItem("login")){
localStorage.setItem("login", "false");
return false;
}
return JSON.parse(localStorage.getItem("login"));
});
// Updating the local storage whenever
// the login state changes
useEffect(() => {
localStorage.setItem("login", JSON.stringify(login));
}, [login]);
// Click Handler updates the login state
// when the button is clicked
const click = () => {
setLogin((prev) => {
return !prev;
});
}
return (
<div className="App">
<Router>
<button onClick={() => click()}>
{login? "Logout" : "Login"}
<Link to={"/admin"}>Admin</Link>
<Link to={"/"}>Home</Link>
<Routes>
<Route path="/" element={<Home />} />
{/* Protecting the Admin Page */}
<Route
path="/admin"
element={
<PrivateRoute login={login}>
<Admin />
</PrivateRoute>
}
/>
</Routes>
</Router>
</div>
);
}
export default App;
第15步:创建服务器,在8000端口监听传入的请求。我们已经创建了一个中间件函数来验证用户。这个中间件函数可以应用于任何路由。
// Importing the required modules
const express = require('express');
const cors = require('cors');
// Creating an express server
const app = express();
// Middleware to parse the data into JSON
app.use(express.json())
// Middleware to accept requests from localhost:3000
app.use(
cors({
origin: "http://localhost:3000",
credentials: true,
})
);
// Middleware Function to authenticate the user
const auth = (req, res, next) => {
console.log(req.body);
if(req.body.logged){
next();
return;
}
res.send({
success: false,
message: "Unauthorized Access"
});
}
// Post request handler for the /admin route
app.post("/admin", auth, (req, res) => {
res.send({
success: true,
message: "Successfully Authenticated"
});
})
app.listen(8000, () => {
console.log("Listening on port 8000")
})
运行应用程序的步骤:
在客户端文件夹中运行以下命令
npm start
在基本目录下运行以下命令
node server.js
输出:
基本网络应用程序
如果一切都在按计划进行,我们应该看到。
- 当我们注销和登录时,服务器端的输出如下
Server-side 输出
- 当我们注销和登录时,在客户端的输出如下
Client-side 输出
Final 输出:
Final 输出