如何使用Node.js和React.js防止对管理页面的访问

  • Post category:jquery

当我们构建一个网站时,经常需要设计一些管理页面来管理网站的不同部分,这些页面只有管理员才能够访问。为了防止其他人访问这些页面,我们需要一些方法来对这些页面进行保护。在这里,我将几种实现这个目标的方式,使用Node.js和React.js。

什么是Node.js和React.js

首先简单介绍一下Node.js和React.js。

Node.js是一个可运行在服务器端的JavaScript运行环境,可以运行JavaScript代码,也可以使用Node.js提供的许多模块进行服务器端开发。

React.js是Facebook开发的一个用于构建用户界面的JavaScript库,通过使用React,我们可以使用组件化的方式构建Web应用程序的用户界面。

通过路由实现页面访问控制

其中一种方式是通过路由实现页面访问控制。具体流程如下:

  1. 安装需要的包:

npm install express express-session

  1. 在Node.js的服务器端代码中添加路由:

“`javascript
const express = require(‘express’);
const session = require(‘express-session’);
const app = express();

// session中间件
app.use(session({
secret: ‘mySecret’,
resave: false,
saveUninitialized: true
}));

// 登陆页面
app.get(‘/login’, (req, res) => {
res.send(‘Please login’);
});

// 普通页面
app.get(‘/normal’, (req, res) => {
if (req.session.authenticated) {
res.send(‘This is a normal page’);
} else {
res.redirect(‘/login’);
}
});

// 管理页面
app.get(‘/admin’, (req, res) => {
if (req.session.authenticated && req.session.isAdmin) {
res.send(‘This is an admin page’);
} else {
res.status(401).send(‘Unauthorized’);
}
});

// 登录验证
app.post(‘/login’, (req, res) => {
if (req.body.username === ‘admin’ && req.body.password === ‘admin’) {
req.session.authenticated = true;
req.session.isAdmin = true;
res.redirect(‘/admin’);
} else if (req.body.username && req.body.password) {
req.session.authenticated = true;
res.redirect(‘/normal’);
} else {
res.redirect(‘/login’);
}
});

app.listen(3000, () => {
console.log(‘Server is running at http://localhost:3000’);
});
“`

  1. 在React.js的前端代码中,使用路由链接到Node.js的服务器代码:

“`javascript
import React from ‘react’;
import { BrowserRouter as Router, Switch, Route, Link, Redirect } from ‘react-router-dom’;

const Login = () => (

Login

);
const Normal = () => (

Normal

This is a normal page

);
const Admin = () => (

Admin

This is an admin page

);

class App extends React.Component {
constructor(props) {
super(props);
this.state = { authenticated: false };
}

   componentDidMount() {
       fetch('/auth', { credentials: 'include' })
           .then(response => response.json())
           .then(data => {
               if (data.authenticated) {
                   this.setState({ authenticated: true });
               }
           });
   }

   render() {
       return (
           <div>
               <h1>React.js and Node.js Example</h1>

               <Router>
                   <nav>
                       <ul>
                           <li><Link to="/normal">Normal Page</Link></li>
                           <li><Link to="/admin">Admin Page</Link></li>
                       </ul>
                   </nav>
                   <Switch>
                       <Route exact path="/login" component={Login} />
                       <Route exact path="/normal" component={Normal} />
                       <Route exact path="/admin" render={() => (
                           this.state.authenticated ? (<Admin />) : (<Redirect to="/login" />)
                       )} />
                   </Switch>
               </Router>
           </div>
       );
   }

}

export default App;
“`

通过路由实现页面访问控制,我们可以设置一个路由,只有在用户已经通过身份验证之后,才可以访问管理页面。如上面的代码所示,我们在“/admin”路由上添加了身份验证的逻辑,只有在用户已经通过身份验证并且是管理员账户才可以访问该路由。

通过JWT实现页面访问控制

另一种方式是通过JWT实现页面访问控制。JWT是一种基于Token的用户身份验证和授权协议,用于在客户端和服务器之间传输安全凭证。

具体流程如下:

  1. 安装需要的包:

npm install express jsonwebtoken cookie-parser

  1. 在Node.js的服务器端代码中添加JWT验证功能:

“`javascript
const express = require(‘express’);
const jwt = require(‘jsonwebtoken’);
const cookieParser = require(‘cookie-parser’);
const app = express();

// 配置 cookie-parser 中间件
app.use(cookieParser());

// 登陆页面
app.get(‘/login’, (req, res) => {
const username = req.query.username;
const password = req.query.password;

   if (username === 'admin' && password === 'admin') {
       const token = jwt.sign({ username: 'admin' }, 'mySecret');
       res.cookie('token', token);
       res.send('Logged in');
   } else {
       res.status(401).send('Unauthorized');
   }

});

// 普通页面
app.get(‘/normal’, (req, res) => {
const token = req.cookies.token;

   if (token) {
       try {
           jwt.verify(token, 'mySecret');
           res.send('This is a normal page');
       } catch (err) {
           res.status(401).send('Unauthorized');
       }
   } else {
       res.status(401).send('Unauthorized');
   }

});

// 管理页面
app.get(‘/admin’, (req, res) => {
const token = req.cookies.token;

   if (token) {
       try {
           const decoded = jwt.verify(token, 'mySecret');
           if (decoded.username === 'admin') {
               res.send('This is an admin page');
           } else {
               res.status(401).send('Unauthorized');
           }
       } catch (err) {
           res.status(401).send('Unauthorized');
       }
   } else {
       res.status(401).send('Unauthorized');
   }

});

app.listen(3000, () => {
console.log(‘Server is running at http://localhost:3000’);
});
“`

  1. 在React.js的前端代码中,使用Fetch API将JWT Token发送到Node.js的服务器代码:

“`javascript
import React from ‘react’;
import { BrowserRouter as Router, Switch, Route, Link } from ‘react-router-dom’;

class Login extends React.Component {
state = { username: ”, password: ” };

   handleChange = (event) => {
       const { name, value } = event.target;
       this.setState({ [name]: value });
   };

   handleSubmit = (event) => {
       event.preventDefault();
       const tokenEndpoint = '/login?username=' + this.state.username + '&password=' + this.state.password;
       fetch(tokenEndpoint)
           .then(response => {
               if (!response.ok) {
                   throw new Error('Network response was not ok');
               }
               return response;
           })
           .then(response => { document.cookie = "token=" + response.text(); })
           .catch(error => alert("Error occurred: " + error));
   }

   render() {
       const { username, password } = this.state;
       return (
           <div>
               <h2>Login</h2>
               <form onSubmit={this.handleSubmit}>
                   <label htmlFor="username">Username:</label><br />
                   <input type="text" id="username" name="username" value={username} onChange={this.handleChange} /><br />
                   <label htmlFor="password">Password:</label><br />
                   <input type="password" id="password" name="password" value={password} onChange={this.handleChange} /><br /><br />
                   <input type="submit" value="Submit" />
               </form>
           </div>
       );
   }

}

const Normal = () => (

Normal

This is a normal page

);
const Admin = () => (

Admin

This is an admin page

);

class App extends React.Component {
constructor(props) {
super(props);
this.state = { authenticated: false };
}

   componentDidMount() {
       fetch('/auth', { credentials: 'include' })
           .then(response => response.json())
           .then(data => {
               if (data.authenticated) {
                   this.setState({ authenticated: true });
               }
           });
   }

   render() {
       return (
           <div>
               <h1>React.js and Node.js Example</h1>

               <Router>
                   <nav>
                       <ul>
                           <li><Link to="/normal">Normal Page</Link></li>
                           <li><Link to="/admin">Admin Page</Link></li>
                       </ul>
                   </nav>
                   <Switch>
                       <Route exact path="/login" component={Login} />
                       <Route exact path="/normal" component={Normal} />
                       <Route exact path="/admin" render={() => (
                           this.state.authenticated ? (<Admin />) : (<Redirect to="/login" />)
                       )} />
                   </Switch>
               </Router>
           </div>
       );
   }

}

export default App;
“`

通过JWT实现页面访问控制,我们可以将用户身份验证的信息存储在一个JWT Token中,并将其发送到客户端。当用户访问受保护的页面时,客户端将Token发送给服务器进行身份验证,如果验证成功,则可以访问该页面。如上面的代码所示,我们在客户端使用Fetch API向Node.js服务器发送带有用户名和密码的请求,服务器会生成一个JWT Token,并将该Token存储在Cookie中。在后续请求中,客户端将Token从Cookie中读取,并发送到服务器端进行身份验证。