settings.xml认证配置
本章是"部署与分发"主题的收尾。入门教程已讲解settings.xml的localRepository和mirrors配置,本章解决远程仓库上传时的身份认证问题。理解servers标签与distributionManagement的id对应关系,是deploy成功的前提。
核心机制
settings.xml中的<servers>标签专门存储远程仓库的认证凭证。当Maven执行mvn deploy(或从需要认证的仓库下载私有构件)时,它会用distributionManagement(或repository)中声明的id作为钥匙,到settings.xml的servers列表中查找匹配的账号密码。
这个设计的精妙之处在于分离:pom.xml是项目级文件,会进入版本控制,不适合存放密码;settings.xml是用户级文件,通常放在本地且不受版本控制管理,是存放敏感凭证的安全场所。
servers标签的结构
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
http://maven.apache.org/xsd/settings-1.0.0.xsd">
<servers>
<server>
<id>feixiang-releases</id>
<username>deployer</username>
<password>{COQLCE6DU6GtcS5P=}</password> <!-- 明文或加密 -->
<filePermissions>664</filePermissions>
<directoryPermissions>775</directoryPermissions>
</server>
<server>
<id>feixiang-snapshots</id>
<username>snapshot-deployer</username>
<password>${env.NEXUS_SNAPSHOT_PASSWORD}</password> <!-- 环境变量引用 -->
</server>
</servers>
</settings>
id对应关系的三条铁律
- 大小写敏感:
feixiang-releases和Feixiang-Releases是两个不同的id - 完全匹配:pom.xml中distributionManagement的
id必须与settings.xml中server的id逐字符相同 - 一id一认证:同一个id只能对应一组username/password,但同一个URL可以配多个id(对应不同权限账号)
密码的三种存储方式
| 存储方式 | 配置写法 | 安全性 | 适用场景 |
|---|---|---|---|
| 明文 | <password>myPassword123</password> | 低 | 个人开发机、学习测试 |
| 加密 | <password>{jSMOWnoM8PL...=}</password> | 中 | 团队共享settings模板 |
| 环境变量 | <password>${env.NEXUS_PASSWORD}</password> | 高 | CI/CD流水线、生产环境 |
Maven 3.2.1+支持${env.变量名}语法引用系统环境变量,这是CI场景的最佳实践——Jenkins/GitHub Actions在运行时注入密码,settings.xml里只留占位符。
生活类比:快递柜与门禁卡
想象飞翔科技大楼的快递收发系统:
- pom.xml中的distributionManagement:快递单上的"收货地址",写明"放到A区货架"还是"B区冷库"。这是公开信息,贴在包裹外面,任何人都能看到。
- settings.xml中的server:你的员工门禁卡。A区货架需要"物流部员工卡",B区冷库需要"冷链权限卡"。门禁卡不会贴在快递单上,而是随身携带。
- id对应关系:快递单上写"A区货架"(id),门禁系统就刷"物流部员工卡"(同id的server)。如果你拿"财务部员工卡"去刷,即使你是公司员工,门禁也会拒绝——id不匹配,权限不通用。
图示
上图展示了pom.xml与settings.xml的id绑定关系。pom.xml只暴露"去哪里"(URL)和"用什么钥匙孔"(id),settings.xml保管"钥匙本身"(凭证)。deploy执行时,Maven用pom.xml的id去settings.xml"对暗号",对上了才能上传,对不上就报401。
完整示例
场景
飞翔科技搭建了Nexus私服,CTO大翔要求:
- 发布仓库(releases)和快照仓库(snapshots)使用不同的账号,实现权限分离
- 小崔和后端团队只能deploy快照,白歌才能deploy发布版
- 密码不能出现在项目代码库中,CI流水线通过环境变量注入
小崔的settings.xml(个人开发机)
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
http://maven.apache.org/xsd/settings-1.0.0.xsd">
<!-- 本地仓库路径(入门已学) -->
<localRepository>D:/maven-repo</localRepository>
<!-- 远程仓库认证(本章重点) -->
<servers>
<server>
<id>feixiang-releases</id>
<username>deployer</username>
<!-- 使用Maven密码加密工具生成的密文 -->
<password>{jSMOWnoM8PLj6E8t+6Ua9QFgQ1Ujqj3yJhxGvLf0pJQ=}</password>
</server>
<server>
<id>feixiang-snapshots</id>
<username>snapshot-deployer</username>
<password>{COQLCE6DU6GtcS5P=}</password>
</server>
</servers>
<!-- 镜像配置(入门已学) -->
<mirrors>
<mirror>
<id>feixiang-central</id>
<mirrorOf>central</mirrorOf>
<url>https://nexus.feixiang.com/repository/maven-public/</url>
</mirror>
</mirrors>
</settings>
李眉的CI流水线settings.xml(Jenkins环境)
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0">
<servers>
<server>
<id>feixiang-releases</id>
<username>jenkins-deployer</username>
<!-- 从Jenkins Credentials注入,不在文件中留明文 -->
<password>${env.NEXUS_RELEASE_PASSWORD}</password>
</server>
<server>
<id>feixiang-snapshots</id>
<username>jenkins-deployer</username>
<password>${env.NEXUS_SNAPSHOT_PASSWORD}</password>
</server>
</servers>
</settings>
Jenkins Pipeline中注入环境变量:
pipeline {
agent any
environment {
NEXUS_RELEASE_PASSWORD = credentials('nexus-release-password')
NEXUS_SNAPSHOT_PASSWORD = credentials('nexus-snapshot-password')
}
stages {
stage('Deploy') {
steps {
sh 'mvn clean deploy -s jenkins-settings.xml'
}
}
}
}
白歌的pom.xml(项目级,入Git)
<distributionManagement>
<repository>
<id>feixiang-releases</id>
<name>飞翔科技发布仓库</name>
<url>https://nexus.feixiang.com/repository/maven-releases/</url>
</repository>
<snapshotRepository>
<id>feixiang-snapshots</id>
<name>飞翔科技快照仓库</name>
<url>https://nexus.feixiang.com/repository/maven-snapshots/</url>
</snapshotRepository>
</distributionManagement>
各角色的deploy验证
小崔(后端开发)测试快照部署:
# 小崔执行deploy,version为SNAPSHOT,走feixiang-snapshots
mvn clean deploy
# Maven用id=feixiang-snapshots去settings.xml找server
# 找到username=snapshot-deployer,密码解密后上传
# 成功:快照部署到私服
白歌(架构师)测试发布部署:
# 白歌先修改version为RELEASE,再deploy
mvn versions:set -DnewVersion=1.2.0
mvn clean deploy
# Maven用id=feixiang-releases去settings.xml找server
# 白歌的账号有releases权限,上传成功
李眉(运维)检查权限隔离:
# 李眉在Nexus后台确认:
# - snapshot-deployer账号只有maven-snapshots仓库的读写权
# - deployer账号只有maven-releases仓库的读写权
# - 小崔即使拿到deployer密码,也无法用feixiang-releases的id上传SNAPSHOT
# (因为pom.xml中SNAPSHOT走feixiang-snapshots id,对应不同账号)
易错点与常见问题
误区一:在pom.xml里写username和password
错误认知:"我把账号密码直接写在pom.xml的distributionManagement里,这样团队成员不用配settings.xml就能deploy。"
纠正:绝对不要这样做。pom.xml是项目文件,会进入Git版本控制。一旦提交,密码将永久留在提交历史中,即使后续删除也无法从Git历史里抹除。而且pom.xml中的<repository>标签不支持username和password子元素——Maven规范不允许在pom.xml中内嵌认证信息。
反例:
<!-- 错误!pom.xml不支持这种写法 -->
<repository>
<id>feixiang-releases</id>
<url>https://nexus.feixiang.com/...</url>
<username>deployer</username> <!-- 非法标签,Maven会忽略 -->
<password>mySecret123</password> <!-- 非法标签,且已泄露 -->
</repository>
正确做法:认证信息严格隔离在settings.xml中,pom.xml只声明id和url。团队新成员入职时,由李眉单独发放settings.xml模板或密码加密指南。
误区二:id不匹配导致401错误却去改密码
错误认知:"deploy报401 Unauthorized,肯定是密码错了,我去Nexus后台重置密码。"
纠正:401错误有两个常见原因,id不匹配比密码错误更隐蔽:
- id拼写不一致:pom.xml里写
feixiang-releases,settings.xml里写feixiang-release(少s) - 大小写不一致:pom.xml里写
Feixiang-Releases,settings.xml里写feixiang-releases
排查方法:
# 查看Maven实际使用的server配置
mvn clean deploy -X
# -X开启debug模式,在日志中搜索"server"关键字
# 你会看到类似:Using server: feixiang-releases (user: deployer)
# 如果看到"Using server: null",说明id没匹配上
反例:小崔花了两小时重置Nexus密码、重启服务,最后发现是pom.xml里id多了个空格feixiang-releases (尾部空格不可见)。
误区三:settings.xml配了server但用错文件
错误认知:"我在~/.m2/settings.xml里配了server,但deploy还是报401。"
纠正:Maven按以下优先级查找settings.xml:
- 命令行指定:
mvn deploy -s /path/to/custom-settings.xml(最高优先级) - 用户级配置:
${user.home}/.m2/settings.xml - 全局配置:
${maven.home}/conf/settings.xml
如果你通过IDEA的Maven设置指定了自定义settings路径,或者CI流水线用了-s参数,那么~/.m2/settings.xml里的配置会被完全忽略。很多开发者在IDEA里配了一套、在~/.m2里配了另一套,两边id不一致,导致本地命令行能deploy,IDEA里却401。
排查方法:
# 查看Maven实际使用的settings.xml路径
mvn help:effective-settings
# 输出中会显示"Effective user-specific configuration settings"的文件路径
小结
settings.xml的servers标签是Maven远程认证的"钥匙串"。核心要点:
- id是唯一的绑定键,pom.xml的distributionManagement与settings.xml的server通过id一一对应
- pom.xml只暴露地址,settings.xml保管凭证,两者分离是安全设计的基石
- 密码优先用环境变量或加密存储,避免明文泄露
- 排查401错误时先检查id匹配,再检查密码正确性
理解servers与distributionManagement的协作关系,才能确保deploy命令在本地开发、团队协作、CI流水线三种场景下都能顺利通过认证。
本章与全局的关系:本章完成了"部署与分发"主题的认证闭环。至此,你已经掌握:distributionManagement配置目标地址、mvn deploy执行上传、settings.xml提供身份认证——三者配合,构成Maven构件分发的完整链路。