Vue过滤特殊字符后为什么SQL注入还能被绕过?

慕容喜静 阅读 25

在Vue项目里处理搜索框输入时,我给后端API加了引号过滤,但测试SQL注入时发现还是能绕过…

具体场景是用户输入搜索词会拼接SQL语句,我在前端用了正则过滤单双引号,但输入” OR 1=1–%20测试时,后端居然返回了全部数据。代码是这样的:

<template>
  <input v-model="searchTerm" @input="filterChars">
</template>

<script>
export default {
  data() {
    return { searchTerm: '' }
  },
  methods: {
    filterChars() {
      this.searchTerm = this.searchTerm.replace(/['"]/g, '')
    }
  }
}
</script>

明明把引号都替换了,为什么攻击者还能用双引号构造注入?测试时用的是Postman传参,后端是PHP的mysqli,难道过滤应该在后端做?但前端过滤不是应该作为第一道防线吗?

我来解答 赞 3 收藏
二维码
手机扫码查看
2 条解答
利娜
利娜 Lv1
这个问题其实暴露了一个很常见的误区,很多人觉得前端过滤能防止SQL注入,但实际上前端的任何处理都不可信,因为攻击者完全可以绕过前端直接和后端交互。你用Postman测试就已经证明了这一点,前端的过滤在这种情况下是完全无效的。

第一步,我们先说为什么你的过滤会被绕过。虽然你在前端替换了单双引号,但SQL注入并不一定依赖引号来构造恶意语句。比如你提到的输入" OR 1=1--%20,这里的双引号可能根本不需要,攻击者可以用其他方式构造逻辑表达式,甚至利用数值比较、注释符等手段完成注入。而且即使你过滤了引号,后端拼接SQL时如果没有正确处理参数,依然会被注入。

第二步,解决这个问题的关键在于后端,而不是前端。前端的过滤只能作为用户体验优化的一部分,比如防止用户误输入非法字符,但它绝不能作为安全防线。真正防止SQL注入的方式是使用参数化查询或者预处理语句。下面我给你一个PHP后端的示例代码,展示如何正确处理SQL查询:


// 假设你使用的是mysqli扩展
$mysqli = new mysqli("localhost", "user", "password", "database");

// 获取用户输入,注意这里不进行任何字符过滤
$searchTerm = $_GET['searchTerm'];

// 使用预处理语句来防止SQL注入
$stmt = $mysqli->prepare("SELECT * FROM table_name WHERE column_name LIKE ?");
$searchTerm = "%" . $searchTerm . "%"; // 添加模糊查询的百分号
$stmt->bind_param("s", $searchTerm); // 绑定参数,"s"表示字符串类型
$stmt->execute();
$result = $stmt->get_result();

// 处理结果
while ($row = $result->fetch_assoc()) {
// 输出或处理数据
echo $row['column_name'];
}


上面这段代码的核心是使用了 preparebind_param 方法,这样无论用户输入什么内容,都会被当作参数处理,而不会直接拼接到SQL语句中。即使输入中包含恶意代码,也不会影响SQL语句的执行。

第三步,如果你还想在前端做一些额外的安全措施,可以补充一些校验规则,但这只是为了提升用户体验,而不是为了安全。比如你可以限制用户输入长度,或者禁止输入某些特殊符号,但这些都不能替代后端的参数化查询。


filterChars() {
// 禁止输入一些特殊字符,但不要依赖这个来做安全防护
this.searchTerm = this.searchTerm.replace(/[;'"\]/g, '');
}


最后再强调一下,前端的安全措施只是锦上添花,真正的安全必须依赖后端的正确实现。SQL注入的根本原因在于后端拼接了未经过滤的用户输入,所以一定要用参数化查询或者ORM框架来避免手动拼接SQL语句。

其实开发的时候经常遇到这种问题,有时候会觉得多写几行代码麻烦,但安全问题一旦出事就是大麻烦,还是老老实实写好预处理吧。
点赞 2
2026-02-16 20:13
UX-爱景
UX-爱景 Lv1
你这个情况我遇到过,前端过滤引号根本防不住SQL注入,官方文档里说得很清楚:输入验证和安全过滤必须在后端做,前端的所谓“防御”只是用户体验层面的。

你看攻击者用的是双引号,但你的正则只替换单双引号字符,而SQL注入可以用十六进制编码、注释符甚至不需要引号。像 OR 1=1-- 这种本来就不依赖引号,拼接SQL的时候直接闭合条件就行,你前端删不删除引号都影响不了最终请求体。

更关键的是,Postman绕过Vue的input事件太容易了,直接发POST请求,根本不会触发你那个filterChars方法。你在前端v-model上处理,只能拦住从界面输入的值,拦不住绕过前端的请求。

真正靠谱的做法是后端用预处理语句(prepared statement),PHP的话就是mysqli_prepare或者PDO:

$stmt = mysqli_prepare($conn, "SELECT * FROM products WHERE name LIKE ?");
$searchTerm = "%" . $_POST['searchTerm'] . "%";
mysqli_stmt_bind_param($stmt, "s", $searchTerm);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);


别再指望前端过滤能防注入了,那顶多叫输入净化,连第一道防线都算不上。真正的防线永远在服务端,用参数化查询,别拼SQL字符串。前端加个提示也好,但别让它背锅安全责任。
点赞 4
2026-02-12 14:07