You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

190 lines
6.2 KiB

#!/bin/bash
# SSO (Casdoor) 单点登录 E2E 测试
#
# 测试账号:
# Casdoor 地址: https://cas.gxxhygroup.com
# 用户名: testuser
# 密码: Test@1234
# 组织: XhyGroup
# 应用: xhy-base
#
# 前置条件:
# 1. 后端服务运行在 localhost:8888
# 2. Casdoor 服务可访问
# 3. base-api.yaml 中 Casdoor 配置正确
BASE_URL="${BASE_URL:-http://localhost:8888/api/v1}"
CASDOOR_URL="${CASDOOR_URL:-https://cas.gxxhygroup.com}"
CASDOOR_USER="${CASDOOR_USER:-testuser}"
CASDOOR_PASS="${CASDOOR_PASS:-Test@1234}"
# 颜色输出
log_info() { echo "[INFO] $1"; }
log_success() { echo "[PASS] $1"; }
log_error() { echo "[FAIL] $1"; }
PASS=0
FAIL=0
assert_ok() {
local desc="$1"
local result="$2"
if [ "$result" = "0" ]; then
log_success "$desc"
PASS=$((PASS + 1))
else
log_error "$desc"
FAIL=$((FAIL + 1))
fi
}
echo ""
echo "========================================="
echo " SSO (Casdoor) 单点登录 E2E 测试"
echo "========================================="
echo ""
# ========== 测试 1: 获取 SSO 登录链接 ==========
log_info "测试 1: 获取 SSO 登录链接"
LOGIN_URL_RESP=$(curl -s "$BASE_URL/auth/sso/login-url")
echo " 响应: $LOGIN_URL_RESP"
# 用 python 或简单方式提取 login_url
LOGIN_URL=""
if echo "$LOGIN_URL_RESP" | grep -q "login_url"; then
LOGIN_URL=$(echo "$LOGIN_URL_RESP" | sed 's/.*"login_url":"\([^"]*\)".*/\1/')
fi
if [ -n "$LOGIN_URL" ]; then
assert_ok "GET /auth/sso/login-url 返回有效的登录链接" "0"
echo " 链接: ${LOGIN_URL:0:100}..."
else
assert_ok "GET /auth/sso/login-url 返回有效的登录链接" "1"
fi
# 验证链接包含必要参数
HAS_PARAMS="0"
echo "$LOGIN_URL" | grep -q "client_id=" || HAS_PARAMS="1"
echo "$LOGIN_URL" | grep -q "redirect_uri=" || HAS_PARAMS="1"
echo "$LOGIN_URL" | grep -q "response_type=code" || HAS_PARAMS="1"
echo "$LOGIN_URL" | grep -q "state=" || HAS_PARAMS="1"
assert_ok "登录链接包含 client_id, redirect_uri, response_type, state" "$HAS_PARAMS"
# ========== 测试 2: Casdoor 服务可达性 ==========
log_info "测试 2: Casdoor 服务可达性"
CASDOOR_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$CASDOOR_URL/.well-known/openid-configuration" 2>/dev/null || echo "000")
echo " OIDC 发现端点状态码: $CASDOOR_STATUS"
if [ "$CASDOOR_STATUS" = "200" ]; then
assert_ok "Casdoor OIDC 发现端点可访问" "0"
else
assert_ok "Casdoor OIDC 发现端点可访问 [HTTP $CASDOOR_STATUS]" "1"
fi
# ========== 测试 3: Casdoor API 登录获取授权码 ==========
log_info "测试 3: Casdoor API 登录"
LOGIN_API_RESP=$(curl -s -X POST "$CASDOOR_URL/api/login" \
-H "Content-Type: application/json" \
-d "{
\"application\": \"xhy-base\",
\"organization\": \"XhyGroup\",
\"username\": \"$CASDOOR_USER\",
\"password\": \"$CASDOOR_PASS\",
\"type\": \"code\"
}" 2>/dev/null || echo '{"status":"error"}')
echo " Casdoor 响应: ${LOGIN_API_RESP:0:200}"
if echo "$LOGIN_API_RESP" | grep -q '"status":"ok"'; then
assert_ok "Casdoor API 登录成功" "0"
elif echo "$LOGIN_API_RESP" | grep -q "not supported"; then
log_info " Casdoor 应用不支持 API 直接登录(需浏览器),跳过"
assert_ok "Casdoor API 可达(需浏览器完成授权)" "0"
else
assert_ok "Casdoor API 登录成功" "1"
fi
# ========== 测试 4: 后端回调处理 (用 Casdoor 授权码) ==========
log_info "测试 4: 后端 SSO 回调"
# 从 Casdoor 响应中提取授权码(data 或 data2 字段)
AUTH_CODE=""
if echo "$LOGIN_API_RESP" | grep -q '"code"'; then
# 提取第一个非 status 的 code 字段
AUTH_CODE=$(echo "$LOGIN_API_RESP" | sed 's/.*"data":"\([^"]*\)".*/\1/' 2>/dev/null)
if [ "$AUTH_CODE" = "$LOGIN_API_RESP" ]; then
AUTH_CODE=$(echo "$LOGIN_API_RESP" | sed 's/.*"data2":"\([^"]*\)".*/\1/' 2>/dev/null)
fi
if [ "$AUTH_CODE" = "$LOGIN_API_RESP" ]; then
AUTH_CODE=""
fi
fi
if [ -n "$AUTH_CODE" ] && [ ${#AUTH_CODE} -gt 5 ]; then
echo " 授权码: ${AUTH_CODE:0:20}..."
# 调用后端回调
CALLBACK_HEADERS=$(curl -s -D - -o /dev/null \
"$BASE_URL/auth/sso/callback?code=$AUTH_CODE&state=test" 2>/dev/null)
HTTP_CODE=$(echo "$CALLBACK_HEADERS" | head -1 | grep -o '[0-9]\{3\}')
LOCATION=$(echo "$CALLBACK_HEADERS" | grep -i "^Location:" | tr -d '\r' | cut -d' ' -f2-)
echo " 回调状态码: $HTTP_CODE"
echo " 重定向到: ${LOCATION:0:100}"
if [ "$HTTP_CODE" = "302" ]; then
assert_ok "后端回调返回 302 重定向" "0"
else
assert_ok "后端回调返回 302 重定向 [实际: $HTTP_CODE]" "1"
fi
if echo "$LOCATION" | grep -q "token="; then
assert_ok "重定向 URL 包含 JWT token" "0"
else
assert_ok "重定向 URL 包含 JWT token" "1"
fi
else
log_info " 无法从 Casdoor API 获取授权码,跳过回调测试"
log_info " (Casdoor 可能需要浏览器交互完成登录)"
fi
# ========== 测试 5: SSO 用户不能密码登录 ==========
log_info "测试 5: SSO 用户密码登录限制"
PASSWORD_LOGIN_RESP=$(curl -s -X POST "$BASE_URL/login" \
-H "Content-Type: application/json" \
-d '{"email":"test@example.com","password":"anypassword"}')
echo " 密码登录响应: $PASSWORD_LOGIN_RESP"
if echo "$PASSWORD_LOGIN_RESP" | grep -q "SSO"; then
assert_ok "SSO 用户密码登录被拒绝,提示使用 SSO" "0"
elif echo "$PASSWORD_LOGIN_RESP" | grep -q "不存在"; then
log_info " SSO 用户尚未创建(需先完成一次浏览器 SSO 登录)"
assert_ok "密码登录未暴露 SSO 用户信息" "0"
elif echo "$PASSWORD_LOGIN_RESP" | grep -q "密码错误"; then
log_info " 存在同邮箱的本地用户(SSO 用户通过 casdoor_id 区分)"
assert_ok "密码登录未暴露 SSO 用户信息" "0"
else
assert_ok "SSO 用户密码登录被拒绝" "1"
fi
# ========== 测试报告 ==========
echo ""
echo "========================================="
echo " SSO 测试报告"
echo "========================================="
echo ""
echo "通过: $PASS"
echo "失败: $FAIL"
echo "总计: $((PASS + FAIL))"
echo ""
if [ $FAIL -eq 0 ]; then
echo "所有 SSO 测试通过!"
exit 0
else
echo "存在失败的测试项"
exit 1
fi