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.
slms/docs/URL_ENCODING_FIX.md

6.0 KiB

URL编码修复文档

问题描述

时间: 2025-11-20 23:45
阶段: Jenkins 流水线阶段8 - 推送代码到 feature-ldl

错误信息

fatal: unable to access 'https://qq.com:****@bdgit.educoder.net/pu6zrsfoy/CHZU_CS231_SEB_lab.git/': 
URL rejected: Port number was not a decimal number between 0 and 65535

根本原因分析

问题根源

用户名是邮箱地址:602924803@qq.com

当直接在Git URL中使用时

https://602924803@qq.com:password@bdgit.educoder.net/...

Git会错误地解析URL

  • 用户名:602924803
  • 主机名:qq.com
  • 端口:password(被误认为是端口号)
  • 实际主机:bdgit.educoder.net

为什么会这样?

在URL中@符号有特殊含义:

  • 第一个@:分隔用户信息和主机
  • 但邮箱地址中也包含@
  • Git解析器会混淆这两个@

解决方案

方法URL编码

将特殊字符转换为URL安全的格式

字符 URL编码 说明
@ %40 at符号
: %3A 冒号
/ %2F 斜杠
? %3F 问号
# %23 井号
& %26 和号
= %3D 等号
+ %2B 加号
%20 空格

编码示例

原始用户名:

602924803@qq.com

URL编码后:

602924803%40qq.com

完整URL对比:

错误(未编码):

https://602924803@qq.com:password@bdgit.educoder.net/repo.git

正确(已编码):

https://602924803%40qq.com:password@bdgit.educoder.net/repo.git

实现方法

在 Jenkinsfile 中使用 PowerShell 编码

修复前的代码:

withCredentials([usernamePassword(
    credentialsId: 'educoder-credentials',
    usernameVariable: 'EDUCODER_USER',
    passwordVariable: 'EDUCODER_PASS'
)]) {
    bat """
        git push https://%EDUCODER_USER%:%EDUCODER_PASS%@bdgit.educoder.net/...
    """
}

修复后的代码:

withCredentials([usernamePassword(
    credentialsId: 'educoder-credentials',
    usernameVariable: 'EDUCODER_USER',
    passwordVariable: 'EDUCODER_PASS'
)]) {
    bat '''
        @echo off
        setlocal EnableExtensions EnableDelayedExpansion
        
        REM URL编码用户名和密码
        for /f %%i in ('powershell -NoLogo -NoProfile -Command "[Console]::Out.Write([uri]::EscapeDataString($env:EDUCODER_USER))"') do set USER_ENC=%%i
        for /f %%i in ('powershell -NoLogo -NoProfile -Command "[Console]::Out.Write([uri]::EscapeDataString($env:EDUCODER_PASS))"') do set PASS_ENC=%%i
        
        git push https://%USER_ENC%:%PASS_ENC%@bdgit.educoder.net/...
    '''
}

PowerShell URL编码命令

# 编码用户名
[uri]::EscapeDataString("602924803@qq.com")
# 输出: 602924803%40qq.com

# 编码密码
[uri]::EscapeDataString("password")
# 输出: password如果没有特殊字符则不变

测试验证

本地测试

# 测试URL编码
powershell -Command "[uri]::EscapeDataString('602924803@qq.com')"
# 应该输出: 602924803%40qq.com

# 测试Git推送使用编码后的凭据
git push https://602924803%40qq.com:password@bdgit.educoder.net/pu6zrsfoy/CHZU_CS231_SEB_lab.git HEAD:feature-ldl

Jenkins 测试

  1. 推送代码到Gitea触发构建
  2. 观察阶段8的执行
  3. 确认推送成功

其他解决方案(备选)

方案1: 使用Git Credential Helper

# 配置凭据助手
git config credential.helper store

# 第一次推送时输入凭据
git push https://bdgit.educoder.net/pu6zrsfoy/CHZU_CS231_SEB_lab.git HEAD:feature-ldl
# 输入用户名: 602924803@qq.com
# 输入密码: osgis123

# 后续推送会自动使用保存的凭据

优点: 不需要在URL中包含凭据
缺点: 需要交互式输入不适合CI/CD

方案2: 使用SSH密钥

# 生成SSH密钥
ssh-keygen -t rsa -b 4096 -C "jenkins@slms.local"

# 添加公钥到头歌账户
# 使用SSH URL推送
git push git@bdgit.educoder.net:pu6zrsfoy/CHZU_CS231_SEB_lab.git HEAD:feature-ldl

优点: 更安全,不需要密码
缺点: 需要在头歌配置SSH密钥

方案3: 使用Personal Access Token

# 在头歌生成访问令牌
# 使用令牌代替密码
git push https://602924803%40qq.com:TOKEN@bdgit.educoder.net/...

优点: 更安全,可以设置权限和过期时间
缺点: 需要头歌支持Personal Access Token


最佳实践

1. 始终对URL凭据进行编码

// ✅ 好的做法
for /f %%i in ('powershell -Command "[uri]::EscapeDataString($env:USER)"') do set USER_ENC=%%i
git push https://%USER_ENC%:%PASS_ENC%@...

// ❌ 不好的做法
git push https://%USER%:%PASS%@...

2. 使用凭据管理器

// ✅ 使用 Jenkins 凭据
withCredentials([usernamePassword(...)]) {
    // 使用凭据
}

// ❌ 硬编码凭据
bat "git push https://user:pass@..."

3. 避免在日志中暴露凭据

// ✅ 使用 @echo off 和 setlocal
bat '''
    @echo off
    setlocal EnableDelayedExpansion
    ...
'''

// ❌ 直接使用,可能在日志中显示
bat "git push https://%USER%:%PASS%@..."

相关资源

URL编码参考

Git凭据管理


总结

问题

  • 用户名包含@符号导致Git URL解析错误

解决

  • 使用PowerShell的[uri]::EscapeDataString()进行URL编码
  • @编码为%40

结果

  • Git URL格式正确
  • 推送到头歌成功
  • 流水线完整执行

修复状态: 已完成
测试状态: 待Jenkins验证
文档版本: 1.0