Files
juwan-backend/deploy/dev/script/test-rl.sh
T
2026-04-06 05:15:08 +08:00

169 lines
4.9 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# 测试 Envoy Lua 双 Cookie XSRF + 登录接口 + 限流头
# 用法:
# ./test-login-xsrf-rl.sh [BASE_URL] [WARM_PATH] [LOGIN_PATH] [COUNT] [INTERVAL]
# 环境变量:
# INSECURE=1 # https 自签时跳过校验
# TOKEN_HEADER=xsrf-token
# USERNAME=testUser
# PASSWORD=string
# PHONE=string
# REMEMBER=true # true/false
# DATA='{"username":"..."}' # 直接提供完整 JSON,将覆盖上面四项
#
# 例子:
# ./test-login-xsrf-rl.sh http://127.0.0.1:8080 /healthz /api/v1/auth/login 25 0.1
set -euo pipefail
BASE_URL="${1:-http://127.0.0.1:8080}"
WARM_PATH="${2:-/healthz}"
LOGIN_PATH="${3:-/api/v1/auth/login}"
COUNT="${4:-20}"
INTERVAL="${5:-0.05}"
METHOD="POST"
CONTENT_TYPE="application/json"
TOKEN_HEADER="${TOKEN_HEADER:-xsrf-token}"
TOKEN_COOKIE="__Host-XSRF-TOKEN"
GUARD_COOKIE="__Host-XSRF-GUARD"
USERNAME="${USERNAME:-testUser}"
PASSWORD="${PASSWORD:-string}"
PHONE="${PHONE:-string}"
REMEMBER="${REMEMBER:-true}"
INSECURE="${INSECURE:-}"
CURL_COMMON=(-sS -L)
[[ -n "${INSECURE}" ]] && CURL_COMMON+=(-k)
tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' EXIT
hdr="$tmpdir/hdr"
echo "# Base=${BASE_URL} Warm=${WARM_PATH} Login=${LOGIN_PATH} Count=${COUNT} Interval=${INTERVAL}s"
# 构造请求体(优先使用 DATA;否则用变量拼装)
build_data() {
if [[ -n "${DATA:-}" ]]; then
DATA_PAYLOAD="${DATA}"
return
fi
# 规范化 REMEMBER 为 true/false
case "${REMEMBER,,}" in
true) REMEMBER=true ;;
false) REMEMBER=false ;;
*) REMEMBER=true ;;
esac
if command -v jq >/dev/null 2>&1; then
DATA_PAYLOAD="$(
jq -n \
--arg username "$USERNAME" \
--arg password "$PASSWORD" \
--arg phone "$PHONE" \
--argjson remember "$REMEMBER" \
'{username:$username,password:$password,phone:$phone,remember:$remember}'
)"
else
# 无 jq 的简易拼装(注意变量里如含双引号会破坏 JSON,生产建议安装 jq)
DATA_PAYLOAD=$(cat <<JSON
{"username":"$USERNAME","password":"$PASSWORD","phone":"$PHONE","remember":$REMEMBER}
JSON
)
fi
}
warm_set_cookies() {
local url="${BASE_URL}${WARM_PATH}"
echo "# 预热: GET ${url} 以获得 CSRF 双 Cookie"
curl "${CURL_COMMON[@]}" -X GET -D "$hdr" -o /dev/null "$url" || true
# 解析 Set-Cookie
local out
out=$(awk '
{
line=$0; gsub("\r","",line);
low=tolower(line);
if (index(low,"set-cookie:")==1) {
sub(/^[Ss]et-[Cc]ookie:[ ]*/, "", line);
split(line, p, /;/); split(p[1], kv, /=/);
name=tolower(kv[1]); val=kv[2];
if (name=="__host-xsrf-token") token=val;
if (name=="__host-xsrf-guard") guard=val;
}
}
END{
if (token) printf("TOKEN=%s\n", token);
if (guard) printf("GUARD=%s\n", guard);
}' "$hdr" || true)
eval "$out" || true
if [[ -z "${TOKEN:-}" || -z "${GUARD:-}" ]]; then
echo "!! 未从响应中解析到 CSRF Cookie,检查 Lua 过滤器是否生效或是否命中过滤链。"
echo "响应头预览:"; head -n 50 "$hdr"
exit 1
fi
COOKIE_HEADER="${TOKEN_COOKIE}=${TOKEN}; ${GUARD_COOKIE}=${GUARD}"
echo "# 已获取 Cookie: ${COOKIE_HEADER}"
}
extract_rl_headers() {
local LIMIT REMAIN RESET RLED
LIMIT=$(grep -i '^x-ratelimit-limit:' "$hdr" 2>/dev/null | head -n1 | awk '{print $2}' | tr -d '\r' || true)
REMAIN=$(grep -i '^x-ratelimit-remaining:' "$hdr" 2>/dev/null | head -n1 | awk '{print $2}' | tr -d '\r' || true)
RESET=$(grep -i '^x-ratelimit-reset:' "$hdr" 2>/dev/null | head -n1 | awk '{print $2}' | tr -d '\r' || true)
RLED=$(grep -i '^x-envoy-ratelimited:' "$hdr" 2>/dev/null | head -n1 | awk '{print $2}' | tr -d '\r' || true)
printf "limit=%s remaining=%s reset=%s ratelimited=%s" "${LIMIT:--}" "${REMAIN:--}" "${RESET:--}" "${RLED:-no}"
}
do_request() {
local with_header="$1" # yes/no
local url="${BASE_URL}${LOGIN_PATH}"
rm -f "$hdr"
if [[ "$with_header" == "yes" ]]; then
CODE=$(curl "${CURL_COMMON[@]}" -X "$METHOD" \
-H "Content-Type: ${CONTENT_TYPE}" \
-H "Cookie: ${COOKIE_HEADER}" \
-H "${TOKEN_HEADER}: ${TOKEN}" \
--data "$DATA_PAYLOAD" \
-D "$hdr" -o /dev/null -w "%{http_code}" \
"$url")
else
CODE=$(curl "${CURL_COMMON[@]}" -X "$METHOD" \
-H "Content-Type: ${CONTENT_TYPE}" \
-H "Cookie: ${COOKIE_HEADER}" \
--data "$DATA_PAYLOAD" \
-D "$hdr" -o /dev/null -w "%{http_code}" \
"$url")
fi
printf "%s code=%s " "$(date '+%H:%M:%S')" "${CODE}"
extract_rl_headers
printf "\n"
}
# 1) 构造登录请求体
build_data
echo "# 登录请求体: ${DATA_PAYLOAD}"
# 2) 预热拿 Cookie
warm_set_cookies
# 3) 负例:不带 xsrf-token 头(应 403
echo "# 负例:不带 XSRF 头,预期 403"
do_request "no"
# 4) 正例:带齐 Cookie + xsrf-token,循环观察限流头
echo "# 正例:带齐 Cookie 与 XSRF 头,开始压测以观测限流头"
for i in $(seq 1 "${COUNT}"); do
printf "#%02d " "$i"
do_request "yes"
sleep "${INTERVAL}"
done