乐途乐途
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
  • 学习路径
  • 第1章 多模块项目深入

    • Reactor构建顺序
    • 继承与聚合组合实践
    • 模块间依赖
  • 第2章 插件体系深入

    • 插件目标goal
    • execution与自定义绑定
    • pluginManagement
  • 第3章 Profile高级应用

    • Profile激活机制
    • Profile与Spring Profile区别
  • 第4章 部署与分发

    • distributionManagement
    • mvn deploy
    • settings.xml认证配置
  • 第5章 CI/CD集成

    • Maven与持续集成
  • 第6章 自定义插件开发

    • 自定义插件开发
  • 第7章 高级依赖管理

    • 快照版本机制
    • 依赖分析工具
  • 第8章 仓库管理深入

    • 仓库组与路由

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对应关系的三条铁律

  1. 大小写敏感:feixiang-releases和Feixiang-Releases是两个不同的id
  2. 完全匹配:pom.xml中distributionManagement的id必须与settings.xml中server的id逐字符相同
  3. 一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大翔要求:

  1. 发布仓库(releases)和快照仓库(snapshots)使用不同的账号,实现权限分离
  2. 小崔和后端团队只能deploy快照,白歌才能deploy发布版
  3. 密码不能出现在项目代码库中,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不匹配比密码错误更隐蔽:

  1. id拼写不一致:pom.xml里写feixiang-releases,settings.xml里写feixiang-release(少s)
  2. 大小写不一致: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:

  1. 命令行指定:mvn deploy -s /path/to/custom-settings.xml(最高优先级)
  2. 用户级配置:${user.home}/.m2/settings.xml
  3. 全局配置:${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远程认证的"钥匙串"。核心要点:

  1. id是唯一的绑定键,pom.xml的distributionManagement与settings.xml的server通过id一一对应
  2. pom.xml只暴露地址,settings.xml保管凭证,两者分离是安全设计的基石
  3. 密码优先用环境变量或加密存储,避免明文泄露
  4. 排查401错误时先检查id匹配,再检查密码正确性

理解servers与distributionManagement的协作关系,才能确保deploy命令在本地开发、团队协作、CI流水线三种场景下都能顺利通过认证。

本章与全局的关系:本章完成了"部署与分发"主题的认证闭环。至此,你已经掌握:distributionManagement配置目标地址、mvn deploy执行上传、settings.xml提供身份认证——三者配合,构成Maven构件分发的完整链路。

上一页
mvn deploy