MST
星途 面试题库

面试题:Node.js Express应用中如何防范SQL注入攻击

假设你的Node.js Express应用与数据库交互,可能会受到SQL注入攻击。请详细阐述如何通过输入验证、参数化查询等手段来防范此类攻击,若使用了ORM框架(如Sequelize),又该如何借助其特性进行防护。
42.4万 热度难度
前端开发Node.js

知识考点

AI 面试

面试题答案

一键面试

输入验证防范SQL注入

  1. 字符串长度限制
    • 在Express应用中,对于接收的用户输入,如表单数据或URL参数,可使用中间件设置字符串长度限制。例如,使用express-validator库:
    const { body } = require('express - validator');
    app.post('/user', [
        body('username').isLength({ max: 50 })
    ], (req, res) => {
        // 处理请求
    });
    
    • 这样可防止用户输入超长字符串来尝试破坏SQL语句结构。
  2. 数据类型验证
    • 确定输入数据的类型。比如,如果期望的是数字类型,可验证输入是否为数字。还是用express - validator
    const { body } = require('express - validator');
    app.post('/product', [
        body('price').isNumeric()
    ], (req, res) => {
        // 处理请求
    });
    
    • 这能避免用户输入非数字字符导致SQL语句错误解析。
  3. 正则表达式验证
    • 对于特定格式的数据,如邮箱、电话号码等,使用正则表达式进行验证。例如验证邮箱:
    const { body } = require('express - validator');
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    app.post('/register', [
        body('email').matches(emailRegex)
    ], (req, res) => {
        // 处理请求
    });
    
    • 确保输入的数据符合预期格式,减少SQL注入风险。

参数化查询防范SQL注入

  1. 原生Node.js MySQL示例
    • 当使用mysql模块与MySQL数据库交互时,使用参数化查询。
    const mysql = require('mysql');
    const connection = mysql.createConnection({
        host: 'localhost',
        user: 'root',
        password: 'password',
        database: 'test'
    });
    const username = req.body.username;
    const query = 'SELECT * FROM users WHERE username =?';
    connection.query(query, [username], (error, results, fields) => {
        if (error) throw error;
        res.send(results);
    });
    
    • 这里?是参数占位符,[username]是参数值数组,数据库驱动会正确处理参数,防止SQL注入。
  2. 原生Node.js PostgreSQL示例
    • 对于pg模块与PostgreSQL数据库交互:
    const { Pool } = require('pg');
    const pool = new Pool({
        user: 'user',
        host: 'localhost',
        database: 'test',
        password: 'password',
        port: 5432,
    });
    const username = req.body.username;
    const query = 'SELECT * FROM users WHERE username = $1';
    pool.query(query, [username], (error, results) => {
        if (error) throw error;
        res.send(results.rows);
    });
    
    • $1是参数占位符,同样通过参数化方式避免SQL注入。

使用Sequelize ORM框架防护SQL注入

  1. 模型定义
    • Sequelize通过模型定义来约束数据。例如定义一个用户模型:
    const Sequelize = require('sequelize');
    const sequelize = new Sequelize('database', 'username', 'password', {
        host: 'localhost',
        dialect:'mysql'
    });
    const User = sequelize.define('user', {
        username: {
            type: Sequelize.STRING,
            allowNull: false
        },
        email: {
            type: Sequelize.STRING,
            allowNull: false,
            validate: {
                isEmail: true
            }
        }
    });
    
    • 这里通过type指定数据类型,validate进行额外验证,从数据层面限制非法输入。
  2. 查询操作
    • 在查询时,Sequelize自动处理参数化。例如查找用户:
    const username = req.body.username;
    User.findOne({ where: { username: username } }).then(user => {
        res.send(user);
    }).catch(error => {
        res.status(500).send(error);
    });
    
    • Sequelize将username作为参数处理,防止SQL注入,无需手动编写参数化查询语句。