必须用maven主密钥加密机制:先用mvn --encrypt-master-password生成主密钥存入settings-security.xml(权限600),再用mvn --encrypt-password加密各server密码,ci/cd应优先使用token或密钥管理器注入凭据。

settings.xml 里明文写 password 是真不行
只要有人能碰得到你的 settings.xml,密码就等于裸奔。CI/CD 机器、共享开发环境、Git 提交历史——任何一个环节泄露,server 的账号就可能被拿去拉私库、推恶意包、甚至反向打内网。Maven 原生不支持明文密码加密存储,但提供了 master-password 加密机制,必须用它,没得选。
用 mvn --encrypt-master-password 生成主密钥
这个命令不是用来加密服务器密码的,而是给整个加密链“上锁”的钥匙。它生成的是一串 Base64 编码的密文,存进 ~/.m2/settings-security.xml。这文件必须严格权限控制(chmod 600),否则 Maven 直接拒绝读取。
- 执行
mvn --encrypt-master-password your-real-master-password(别用弱口令,也别记在文本里) - 把输出结果包进
<settingssecurity><master>xxx</master></settingssecurity>,保存为~/.m2/settings-security.xml - Linux/macOS 下确认:
ls -l ~/.m2/settings-security.xml显示权限是-rw------- - Windows 用户注意:Maven 会尝试读
%USERPROFILE%\.m2\settings-security.xml,路径和权限模型不同,建议用 WSL 或 CI 环境统一验证
用 mvn --encrypt-password 加密每个 server 密码
主密钥设好后,才能对具体服务器的 password 加密。每次加密都依赖当前机器上的 settings-security.xml 和其中的 master,换机器就得重配主密钥——这是设计使然,不是 bug。
- 运行
mvn --encrypt-password your-server-password,输出类似{COQLCE6DU6GtcS5P=}这样的字符串 - 把它填进
settings.xml对应<server></server>的<password></password>标签里(保留花括号) - 别手敲、别复制错字符,
{和}必须完整,少一个 Maven 就报org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException - 加密后的密码只在本机 + 本用户下有效;CI 流水线要用服务账户部署时,必须在对应 runner 上重复生成主密钥和密码密文
CI/CD 中避免硬编码,优先走环境变量或密钥管理器
即使用了加密,把 settings-security.xml 和加密后的 password 一起塞进 Git 或镜像,依然等于把钥匙和锁放一起。生产级做法是绕过 settings.xml 密码字段,改用更可控的方式注入认证凭据。
- 很多私库(Nexus、Artifactory)支持 token 认证,token 可设有效期、作用域、可轮换,比密码安全得多;配置时用
<username></username>+<password></password>传 token 即可 - GitHub Packages、GitLab Registry 等平台推荐用
Personal Access Token或CI_JOB_TOKEN,通过-Dpassword=xxx或环境变量MAVEN_PASSWORD注入,再在settings.xml里用${env.MAVEN_PASSWORD} - 企业级场景直接对接 HashiCorp Vault、AWS Secrets Manager,用插件或启动脚本动态写入临时
settings.xml,用完即焚
主密钥和加密密码的绑定关系很脆弱,路径、权限、JVM 字符编码稍有偏差就会解密失败,报错往往只显示“invalid master password”这种废话。真要排查,先确认 settings-security.xml 存在且可读,再检查 mvn -v 输出的 Java 版本是否和加密时一致——跨 JDK 大版本(比如 JDK 8 加密、JDK 17 解密)大概率失败。










