MST

星途 面试题库

面试题:JavaScript构建Node HTTP客户端与服务器的安全加固要点

在使用JavaScript构建Node HTTP客户端与服务器时,会面临多种安全风险。请详细阐述针对常见安全漏洞(如SQL注入、XSS、CSRF等),在客户端和服务器端分别应采取哪些具体的安全加固措施,并给出相关代码示例或配置说明。
31.8万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

SQL注入

  • 服务器端
    • 使用参数化查询:在Node.js中,对于MySQL数据库,使用mysql模块时可以这样做。例如:
const mysql = require('mysql');
const connection = mysql.createConnection({
  host: 'localhost',
  user: 'root',
  password: 'password',
  database: 'test'
});

const username = 'testUser';
const query = 'SELECT * FROM users WHERE username =?';
connection.query(query, [username], (error, results, fields) => {
  if (error) throw error;
  console.log(results);
});
connection.end();
- **输入验证**:使用`express-validator`库验证输入。例如:
const { check, validationResult } = require('express-validator');
const express = require('express');
const app = express();

app.post('/login', [
  check('username').isLength({ min: 3 }),
  check('password').isLength({ min: 6 })
], (req, res) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    return res.status(422).json({ errors: errors.array() });
  }
  // 处理登录逻辑
});
  • 客户端:客户端一般不直接与数据库交互,主要是通过向服务器发送经过验证的数据。确保在发送数据前,数据已经按照服务器要求的格式进行了处理,比如在表单提交前,使用JavaScript验证输入格式。例如:
<!DOCTYPE html>
<html>

<head>
  <title>Form Validation</title>
</head>

<body>
  <form id="loginForm">
    <label for="username">Username:</label>
    <input type="text" id="username" name="username" />
    <br />
    <label for="password">Password:</label>
    <input type="password" id="password" name="password" />
    <br />
    <input type="submit" value="Submit" />
  </form>
  <script>
    document.getElementById('loginForm').addEventListener('submit', function (e) {
      const username = document.getElementById('username').value;
      const password = document.getElementById('password').value;
      if (username.length < 3) {
        alert('Username must be at least 3 characters long');
        e.preventDefault();
      }
      if (password.length < 6) {
        alert('Password must be at least 6 characters long');
        e.preventDefault();
      }
    });
  </script>
</body>

</html>

XSS(跨站脚本攻击)

  • 服务器端
    • 输出编码:在Node.js的Express应用中,使用DOMPurify库对输出到客户端的数据进行净化。例如:
const express = require('express');
const DOMPurify = require('dompurify');
const app = express();

app.get('/user/:username', (req, res) => {
  const username = req.params.username;
  const cleanUsername = DOMPurify.sanitize(username);
  res.send(`Welcome, ${cleanUsername}`);
});
  • 客户端
    • 设置HTTP - Only Cookies:在Node.js的Express应用中,可以设置cookie-parser中间件来设置HTTP - Only Cookies。例如:
const express = require('express');
const cookieParser = require('cookie-parser');
const app = express();
app.use(cookieParser());

app.get('/setCookie', (req, res) => {
  res.cookie('sessionId', '1234567890', { httpOnly: true });
  res.send('Cookie set');
});
- **输入验证和过滤**:在客户端使用正则表达式等方法对输入进行验证。例如,验证输入是否为合法的URL:
function isValidURL(str) {
  const pattern = new RegExp('^(https?:\\/\\/)?' + // protocol
    '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name
    '((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address
    '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path
    '(\\?[;&a-z\\d%_.~+=-]*)?' + // query string
    '(\\#[-a-z\\d_]*)?$', 'i'); // fragment locator
  return pattern.test(str);
}

CSRF(跨站请求伪造)

  • 服务器端
    • 使用CSRF令牌:在Node.js的Express应用中,使用csurf中间件。例如:
const express = require('express');
const csrf = require('csurf');
const csrfProtection = csrf({ cookie: true });
const app = express();

app.use(csrfProtection);

app.get('/form', (req, res) => {
  res.render('form', { csrfToken: req.csrfToken() });
});

app.post('/submit', csrfProtection, (req, res) => {
  // 处理表单提交
  res.send('Form submitted successfully');
});

在HTML表单中需要包含CSRF令牌:

<!DOCTYPE html>
<html>

<head>
  <title>CSRF Protected Form</title>
</head>

<body>
  <form action="/submit" method="post">
    <input type="hidden" name="_csrf" value="{{csrfToken}}">
    <input type="submit" value="Submit">
  </form>
</body>

</html>
  • 客户端:确保在每次请求(特别是POST等修改数据的请求)中,携带服务器生成的CSRF令牌。在JavaScript中,从页面中获取CSRF令牌并添加到请求头或请求体中。例如,使用fetch
const csrfToken = document.querySelector('input[name="_csrf"]').value;
fetch('/submit', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-CSRF-Token': csrfToken
  },
  body: JSON.stringify({ data: 'example' })
})
 .then(response => response.json())
 .then(data => console.log(data));