Bash脚本中Curl安全头与列表匹配异常,是否需解码?
问题根源与修复方案
你的匹配失败主要不是解码问题,而是脚本在处理curl输出和配置文件时,存在几个关键逻辑错误,导致对比的内容不匹配:
核心问题分析
- 对比对象不统一:配置文件读取的是安全头名称(比如
content-security-policy),但curl读取的是完整的头行(名称+值)(比如content-security-policy: default-src 'self'),两者内容完全不同,自然无法匹配。 - curl输出未清理:curl的
-I输出包含HTTP状态行(如HTTP/2 200)、空白行,以及Windows风格的回车符\r,这些会被错误加入数组,干扰匹配。 - 头名称的空格问题:部分响应头会带前导空格(如
X-Frame-Options: DENY),转小写后会变成x-frame-options,和配置文件中的无空格名称不匹配。 - 数组非空判断错误:
if [[ -n ArrayResult[@] ]]写法错误,无法正确判断数组是否为空。
修复后的完整脚本
#!/bin/bash declare -a LIST_HEADERS # 显式声明为数组 declare -a CURL_HEADERS RED='\033[0;31m' NC='\033[0m' # No Color GREEN='\033[0;32m' # 1. 从配置文件读取安全头名称列表 while IFS= read -r value; do # 去掉引号、转小写、去除前后空白 value=$(echo "$value" | tr -d '"' | tr '[:upper:]' '[:lower:]' | xargs) # 跳过空行 [[ -n "$value" ]] && LIST_HEADERS+=("$value") done < "${CONFIG[cfg]}/headersList.cfg" # 2. 通过curl获取站点安全头名称(仅提取名称) while IFS= read -r header; do # 提取头名称(冒号前的部分)、转小写、去前后空白 header_name=$(echo "$header" | cut -d':' -f1 | tr '[:upper:]' '[:lower:]' | xargs) [[ -n "$header_name" ]] && CURL_HEADERS+=("$header_name") done < <(curl -sIk 'https://google.com' | grep -v "^HTTP/" | tr -d '\r') # 3. 对比两个数组,收集未匹配的安全头 ArrayResult=() for expected_header in "${LIST_HEADERS[@]}"; do found=0 for actual_header in "${CURL_HEADERS[@]}"; do if [[ "$expected_header" == "$actual_header" ]]; then found=1 break fi done [[ $found -eq 0 ]] && ArrayResult+=("$expected_header") done # 4. 输出结果 if [[ ${#ArrayResult[@]} -gt 0 ]]; then echo -e "${RED}以下安全头未在目标站点检测到:${NC}" echo "数量: ${#ArrayResult[@]}" for header in "${ArrayResult[@]}"; do echo "- $header" done else echo -e "${GREEN}所有配置的安全头均已在目标站点检测到${NC}" fi
关键修复点说明
- 统一对比对象:从curl输出中用
cut -d':' -f1提取头名称,确保和配置文件的头名称格式一致。 - 清理curl输出:用
grep -v "^HTTP/"过滤状态行,tr -d '\r'去除回车符,避免不可见字符干扰。 - 空白处理:用
xargs去除头名称前后的空白字符,解决带空格的头名称匹配问题。 - 数组声明:显式用
declare -a声明数组,避免潜在的变量类型问题。 - 修正非空判断:用
${#ArrayResult[@]} -gt 0正确判断数组是否为空。
关于解码的补充
如果你的配置文件或响应头包含URL编码的字符(这种情况极少),才需要用urlencode/urldecode工具处理,但安全头名称本身不会包含编码字符,所以无需额外解码。
内容的提问来源于stack exchange,提问作者Vadim71
相关产品推荐
相关产品推荐

