特殊字符如何过滤拦截

wen 开源项目 28

本文目录导读:

特殊字符如何过滤拦截

  1. 核心原则
  2. 后端过滤拦截(核心)
  3. 前端过滤拦截(用户体验层)
  4. 服务端中间件/网关层过滤
  5. 特定场景的过滤方案
  6. 总结建议

过滤特殊字符通常是为了防止注入攻击(如SQL注入、XSS攻击)、数据清洗格式校验

过滤拦截的方式取决于使用场景(前端/后端、技术栈)以及“特殊字符”的具体定义,以下是几种主流且有效的处理方案:

核心原则

  1. 后端必须做:前端过滤仅用于用户体验,后端是安全底线。
  2. 不要只依赖黑名单:黑名单容易被绕过,优先采用白名单(只允许特定字符)或转义(Escaping)
  3. 视语境而定:不同的上下文(HTML、SQL、URL、JSON)对特殊字符的定义不同。

后端过滤拦截(核心)

通用防注入:使用参数化查询(Prepared Statements)

这是防止SQL注入最有效的方法,它从根本上避免了拼接SQL语句。

  • 错误做法

    # Python (易受攻击)
    cursor.execute("SELECT * FROM users WHERE name = '" + user_input + "'")
  • 正确做法

    # Python (参数化查询)
    cursor.execute("SELECT * FROM users WHERE name = %s", (user_input,))

输出转义(针对XSS攻击)

将数据输出到HTML页面时,进行转义,而不是直接输出。

  • Java (JSP/Servlet):使用 StringEscapeUtils.escapeHtml4(input)
  • Python (Flask/Django):模板引擎默认自动转义(如 {{ variable }}
  • JavaScript (Node.js):使用 html-entities
  • 示例:将 <script>alert('x')</script> 转义为 &lt;script&gt;alert('x')&lt;/script&gt;

使用库函数过滤(白名单与黑名单结合)

在Java/Spring中,可以使用成熟的过滤库:

  • OWASP Java HTML Sanitizer:只允许安全的HTML标签。
  • AntiSamy:定义策略文件(policy.xml)来限制允许的字符和标签。

示例(Java + 自定义过滤器拦截请求):

// 自定义过滤器,拦截所有请求,清理特殊字符
public class XSSFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
        // 1. 获取请求参数
        // 2. 遍历参数,替换或删除 < > " ' ( ) & # 等字符
        String cleanValue = originalValue.replaceAll("<", "&lt;").replaceAll(">", "&gt;");
        // 或者直接删除: originalValue.replaceAll("[<>\"'()]", "");
        // 3. 将清洗后的参数放回Request (通过自定义RequestWrapper)
        chain.doFilter(wrappedRequest, res);
    }
}

白名单示例(推荐):

// Node.js / JavaScript (仅允许字母、数字、中文、下划线)
function filterInput(str) {
    return str.replace(/[^a-zA-Z0-9\u4e00-\u9fa5_]/g, '');
}

前端过滤拦截(用户体验层)

前端拦截不能替代后端拦截,主要用于提升用户反馈速度。

输入框监听(实时拦截)

通过 JavaScript 阻止非法字符输入。

<input type="text" id="username" />
<script>
  document.getElementById('username').addEventListener('keydown', function(e) {
      // 只允许输入字母、数字、下划线
      var allowed = /[a-zA-Z0-9_]/;
      var key = String.fromCharCode(e.keyCode);
      if (!allowed.test(key) && e.keyCode !== 8 && e.keyCode !== 46) { // 允许退格和删除
          e.preventDefault();
      }
  });
</script>

表单提交时校验(拦截提交)

在提交前拦截,并给出提示。

function validateForm() {
    var input = document.getElementById('comment').value;
    // 检测是否包含非法字符 (HTML标签)
    if (/[<>"'&]/.test(input)) {
        alert('输入内容包含非法特殊字符,请修改!');
        return false;
    }
    return true;
}

使用输入框的 pattern 属性(HTML5)

最简单的拦截方式,无需 JS,但不支持所有浏览器。

<input type="text" pattern="[a-zA-Z0-9]+" title="仅允许英文和数字" required>

服务端中间件/网关层过滤

如果系统有多种后端语言,可以在统一的网关(Nginx、API Gateway、WAF)上拦截。

Nginx + Lua/ModSecurity

通过 Nginx 的 ngx_lua 模块或 ModSecurity 模块,在请求到达后端之前,直接拦截。

# Nginx 简单过滤 (仅示例,不推荐用于生产)
if ($query_string ~* "(\<|>|'|\"|%27|%3C|%3E)") {
    return 403;
}

Web应用防火墙(WAF)

商业WAF(如Cloudflare、AWS WAF、阿里云WAF)可以智能识别和拦截SQL注入、XSS等攻击流量,这是最省心的方式。


特定场景的过滤方案

场景 特殊字符 推荐过滤方式
SQL命令 exec 参数化查询(首选),绝不动态拼接。
HTML/XML < > & HTML实体转义&lt; &gt; &quot; &#x27; &amp;
Javascript < > eval JSON.stringify() 或 Base64编码输出。
URL参数 & 空格 URL编码encodeURIComponent(value)
文件路径 \0 白名单路径 + basename() 函数。
命令行 & \n > 禁止直接拼接系统命令,使用API或沙箱。

总结建议

  1. 层级防御:前端(防误触) + 后端(核心防线,使用参数化查询 + 输出转义) + 网关/WAF(边界防御)。
  2. 不要试图“清理” SQL语句:使用预编译是终点。
  3. 特殊字符定义要清晰:是只过滤HTML标签?还是只防SQL注入?还是在比如用户名等场景下只需要字母数字?明确需求后,选择对应的过滤策略。

抱歉,评论功能暂时关闭!