新闻详情

新闻详情

首页 / 资讯中心 / 详情

Jenkins密码重置实战:通过config.xml恢复管理员访问

发布时间:2026/10/2 11:01:04来源:尧图网络
Jenkins密码重置实战:通过config.xml恢复管理员访问
1. 项目概述当Jenkins登录界面变成“拦路虎”这七步是运维人最该收藏的应急手册Jenkins忘记登录密码这件事听起来像个小问题但真发生在凌晨三点的生产环境部署前它就是压垮人的最后一根稻草。我第一次遇到是在给客户做CI/CD链路加固时安全策略要求定期轮换管理员密码结果交接文档里漏写了密钥保管路径第二天早上构建任务全卡在认证环节——没人能进控制台没人能改配置连日志都得靠SSH翻容器日志文件硬查。这不是理论风险而是每天都在真实发生的运维现场困境。核心关键词就三个Jenkins、密码、config.xml它们串起了整个恢复逻辑链——Jenkins本身不存明文密码所有用户凭证都由SecurityRealm组件管理而全局安全管理Global Security Configuration的开关、认证方式、甚至管理员账户的哈希值全部固化在config.xml这个单点配置文件里Docker环境只是让这个问题更典型容器重启后配置卷没挂对或者镜像层覆盖了修改导致你改完文件一重启又回到原点。这篇文章不是教你怎么“破解”系统而是用Jenkins官方机制允许的方式通过直接干预配置文件来重置凭证。适合三类人刚接手老项目的运维新人别再问前任要密码了、Docker化部署的DevOps工程师重点讲清卷挂载和权限陷阱、以及被临时授权接管系统的开发同学不需要sudo权限也能操作。下面这七步每一步我都标出了执行前提、风险等级和替代方案因为真正的应急处理从来不是照着步骤点鼠标而是清楚每一步在改什么、为什么必须这么改。2. 核心原理拆解为什么改config.xml就能重置密码Jenkins认证体系的真实结构2.1 Jenkins认证不是“数据库查密码”而是“配置驱动的插件链”很多人误以为Jenkins像传统Web应用一样把密码存在某个数据库表里所以总想着去MySQL里搜hash值。这是根本性误解。Jenkins的认证体系是纯配置驱动的它的SecurityRealm安全域本质是一个Java接口实现具体用哪种认证方式完全取决于config.xml中securityRealm节点的内容。当你在Web界面勾选“Jenkins专有用户数据库”时系统实际写入的是hudson.security.HudsonPrivateSecurityRealm这个类的XML实例选LDAP则写入hudson.security.LDAPSecurityRealm。而密码存储方式又由SecurityRealm内部的UserDetailsService决定——对于内置数据库它用的是hudson.model.User类的password字段这个字段存的不是明文而是经过BCryptPasswordEncoder加密的哈希值注意不是MD5不是SHA1是带盐的BCrypt这也是为什么不能用彩虹表暴力破解的原因。关键点在于这个哈希值就明明白白写在config.xml里和user节点并列。我翻过Jenkins 2.361的源码在hudson.model.User的getConfigFile()方法里它直接把用户对象序列化成XML写入$JENKINS_HOME/users/{username}/config.xml而管理员账户的凭证就藏在主config.xml的authorizationStrategy关联的permission节点之前那个securityRealm块里。所以重置密码的本质不是破解哈希而是用一个已知明文比如admin生成新哈希替换掉旧哈希——这完全合法且Jenkins启动时会自动加载新配置。2.2 Docker环境下的特殊性配置持久化才是成败关键Docker让这个问题变得高频但也埋了更深的坑。很多人执行完七步重置重启容器后密码又变回旧的根本原因就出在卷挂载的粒度和时机上。标准Docker命令docker run -v /data/jenkins:/var/jenkins_home jenkins/jenkins:lts看似挂载了整个家目录但实际执行时Jenkins镜像的ENTRYPOINT脚本会在容器首次启动时把镜像内置的/usr/share/jenkins/ref/目录下的默认配置包括初始的config.xml复制到/var/jenkins_home。如果你的宿主机/data/jenkins是空目录这个复制就会发生但如果/data/jenkins里已经有旧配置复制就被跳过。问题来了你改的是宿主机上的config.xml但Jenkins进程读取的是容器内/var/jenkins_home路径下的文件——这两个路径是否真的指向同一物理位置我见过最典型的错误是用了绑定挂载bind mount但权限设为ro只读或者挂载时用了:z或:ZSELinux标签却没配对导致容器内进程无法写入重启后配置回滚。更隐蔽的是Docker Compose场景volumes:下写的是./jenkins-data:/var/jenkins_home但.gitignore里把jenkins-data加进了忽略列表导致团队成员拉代码时这个目录是空的每次docker-compose up都触发镜像默认配置覆盖。所以Docker环境下第一步永远不是改文件而是确认docker inspect container_name输出里的Mounts字段看Source和Destination是否严格对应且Mode是rw。2.3 全局安全管理Global Security Configuration的双刃剑效应标题里提到的“全局安全管理”其实是Jenkins安全模型的总开关。它控制两件事谁有权限登录SecurityRealm以及登录后能做什么AuthorizationStrategy。很多人重置密码后还是登不进去是因为只改了securityRealm却忽略了authorizationStrategy里可能存在的hudson.security.FullControlOnceLoggedInAuthorizationStrategy登录即全权或更严格的hudson.security.ProjectMatrixAuthorizationStrategy基于项目的矩阵权限。后者需要你在permission节点里明确赋予admin用户hudson.model.Hudson.Administer权限否则即使密码正确也会被拦在首页报403。我在某金融客户现场就遇到过他们启用了Project Matrix并在config.xml里删掉了permissionhudson.model.Hudson.Administer:admin/permission这一行结果重置密码后管理员账号只能看到“没有权限访问此页面”。所以第七步“验证权限”不是可选项而是必选项。另外disableSignup和enableCaptcha这两个开关也值得警惕——如果disableSignup设为true意味着除了配置文件里明确定义的用户其他人无法注册而enableCaptcha开启时登录界面会多一个验证码但它的校验逻辑依赖JENKINS_HOME下的captcha子目录如果这个目录权限不对比如属主是root而Jenkins进程以jenkins用户运行会导致验证码加载失败整个登录框灰掉。这些细节恰恰是网上90%的教程不会提但线上故障里高频出现的点。3. 实操七步详解从定位文件到验证权限每一步的现场记录与参数推演3.1 第一步精准定位JENKINS_HOME路径——别在错的目录里改一辈子这一步看似简单却是90%失败案例的起点。很多人直接cd /var/lib/jenkins就开干结果发现里面空空如也。正确姿势是先确认Jenkins进程的实际工作目录。如果是Linux服务模式执行systemctl status jenkins在输出里找ExecStart行通常会看到类似/usr/bin/java -DJENKINS_HOME/data/jenkins ...的参数-DJENKINS_HOME后面的路径就是真·家目录。如果是Dockerdocker exec -it container_name sh进入容器后第一件事不是ls而是ps aux | grep java找到Jenkins启动命令从中提取-Djenkins.home参数值。我遇到过最离谱的情况是客户用K8s部署env:里定义了JENKINS_HOME/workspace但volumeMounts:挂载的是/var/jenkins_home导致进程读取/workspace/config.xml而你改的是/var/jenkins_home/config.xml——两个文件物理隔离。确认路径后立刻验证可写性touch $JENKINS_HOME/test.tmp rm $JENKINS_HOME/test.tmp。如果报Permission denied说明用户权限不对。Jenkins官方镜像默认用UID 1001运行所以宿主机挂载目录的属主必须是1001或者用chown -R 1001:1001 /data/jenkins。千万别用chmod 777这会触发Jenkins的安全保护机制启动时直接报错退出。这里有个经验技巧在$JENKINS_HOME下执行ls -ld .看输出第三列属主和第四列属组是否匹配Jenkins进程UID/GID不匹配就chown比猜权限数字靠谱得多。3.2 第二步备份原始config.xml——不是仪式感是救命绳执行任何配置修改前备份必须是原子操作。我坚持用带时间戳的cp而不是mv因为mv会丢失原始文件的inode信息万一备份文件损坏你连恢复原始状态的线索都没了。命令是cp -p $JENKINS_HOME/config.xml $JENKINS_HOME/config.xml.backup.$(date %Y%m%d_%H%M%S)。-p参数保留权限、属主、时间戳这对后续排查权限问题至关重要。备份后立刻校验sha256sum $JENKINS_HOME/config.xml $JENKINS_HOME/config.xml.backup.*对比哈希值确保一致。为什么强调校验因为有些文件系统如NFS在cp过程中可能因网络抖动丢字节肉眼看着文件大小一样但内容已损坏。备份文件必须和原文件在同一文件系统下避免跨文件系统cp时的元数据丢失。更进一步我会把备份文件scp到另一台机器scp $JENKINS_HOME/config.xml.backup.* adminbackup-server:/backup/jenkins/。这不是过度防护而是经历过一次因磁盘坏道导致备份文件也损坏的惨痛教训。线上环境备份的可靠性永远大于备份的速度。3.3 第三步生成新的BCrypt密码哈希——别用在线工具自己算才安心网上一堆“Jenkins密码生成器”网站输入明文就给你返回哈希但你能信吗哈希算法本身是公开的但Jenkins用的BCrypt实现有特定参数strength10迭代次数2^101024且盐值salt是随机生成的。自己生成才能确保兼容性。最稳妥的方式是用Jenkins自带的jenkins-cli.jar但它需要已登录的凭据——这正是我们缺失的。所以退而求其次用Groovy脚本因为Jenkins启动时会加载所有Groovy库。在$JENKINS_HOME下创建临时脚本gen_hash.groovyimport org.jvnet.hudson.crypto.Encryption println Encryption.encrypt(your_new_password)然后执行java -cp $JENKINS_HOME/war/WEB-INF/lib/*.jar groovy.lang.GroovyShell gen_hash.groovy。如果报ClassNotFoundException说明路径不对改成java -cp $JENKINS_HOME/WEB-INF/lib/*.jar groovy.lang.GroovyShell gen_hash.groovyJenkins 2.200版本路径变更。如果连groovy.lang.GroovyShell都找不到说明你的Jenkins版本太老2.100那就用Python一行命令python3 -c import bcrypt; print(bcrypt.hashpw(byour_new_password, bcrypt.gensalt(rounds10)).decode())。注意rounds10必须显式指定因为Jenkins硬编码了这个值用其他轮数生成的哈希Jenkins启动时会拒绝识别。生成的哈希长这样$2a$10$abc123...开头$2a$表示BCrypt v2a10是轮数后面是盐值和密文。把它完整复制下来准备替换。3.4 第四步编辑config.xml——精准定位只动该动的节点打开$JENKINS_HOME/config.xml用vim或nano绝对不要用Windows记事本或TextEdit它们会插入BOM头或用\r\n换行导致Jenkins解析失败。搜索关键词securityRealm定位到类似这样的块securityRealm classhudson.security.HudsonPrivateSecurityRealm disableSignupfalse/disableSignup enableCaptchafalse/enableCaptcha /securityRealm在/securityRealm闭合标签前插入用户定义节点。关键点来了不是所有Jenkins版本都用同一个节点名。Jenkins 2.164版本用的是users列表而老版本2.100用的是user单节点。你要根据securityRealm class...里的类名判断如果是HudsonPrivateSecurityRealm就用新格式如果是LegacySecurityRealm就用老格式。新格式插入users hudson.model.User idadmin/id passwordHash$2a$10$your_generated_hash_here/passwordHash /hudson.model.User /users老格式插入user idadmin/id passwordHash$2a$10$your_generated_hash_here/passwordHash /user提示id必须和你要登录的用户名完全一致区分大小写。如果Jenkins里创建的是Admin首字母大写这里就必须写idAdmin/id写admin会创建新用户而非覆盖。3.5 第五步检查并修正authorizationStrategy——没有权限密码再对也白搭这一步常被跳过但它是登录成功的最后屏障。继续在config.xml里搜索authorizationStrategy找到类似authorizationStrategy classhudson.security.ProjectMatrixAuthorizationStrategy permissionhudson.model.Hudson.Administer:anonymous/permission /authorizationStrategy问题就出在anonymous上——它给了游客全权但没给admin用户任何权限。你需要添加一行permissionhudson.model.Hudson.Administer:admin/permission。如果class是FullControlOnceLoggedInAuthorizationStrategy那它默认给所有已登录用户全权可以跳过此步。但为了保险我还是会加上因为有些定制插件会覆盖这个策略。另一个坑是denyAnonymousReadAccesstrue/denyAnonymousReadAccess如果设为true意味着未登录用户连首页都看不到这没问题但如果设为false而你的authorizationStrategy又没配权限就会出现“登录成功但页面空白”的诡异现象。所以原则是只要authorizationStrategy存在就必须确保目标用户名出现在至少一个permission节点的冒号右边。用grep -n permission $JENKINS_HOME/config.xml快速定位所有权限行人工核对。3.6 第六步重启Jenkins服务——不是简单的kill而是优雅的reload很多人kill -9 $(pgrep -f jenkins)结果Jenkins没来得及写入内存中的配置就死了下次启动还是旧状态。正确做法分场景Systemd服务sudo systemctl restart jenkins它会先发SIGTERM给进程等待Jenkins完成关闭流程保存session、flush日志再启动新实例。Docker容器docker restart container_name比docker stop docker start更可靠因为它保持网络和卷状态。裸机Java进程curl -X POST http://localhost:8080/exit需开启--httpPort8080 --ajp13Port-1参数这是Jenkins内置的优雅关闭端点。重启后立刻检查日志tail -f $JENKINS_HOME/logs/jenkins.log看是否有INFO: Started ServerConnector...启动成功或SEVERE: Failed to initialize配置错误。如果看到java.lang.RuntimeException: Failed to serialize hudson.model.User#passwordHash说明你粘贴的哈希值格式错了可能是多了空格或用了中文引号。此时立刻用备份文件恢复cp $JENKINS_HOME/config.xml.backup.* $JENKINS_HOME/config.xml再重试。3.7 第七步登录验证与权限测试——用三个动作确认万无一失别急着关终端用三个最小动作验证基础登录浏览器访问http://your-jenkins-url/login输入新密码看是否跳转到Dashboard。如果卡在登录页按F12打开开发者工具切到Console标签看是否有403 Forbidden或500 Internal Error前者是权限问题后者是配置XML语法错误。权限验证登录后点击右上角用户名 →Configure看能否进入个人配置页。如果提示“您没有权限执行此操作”说明authorizationStrategy没生效回第四步检查。功能验证新建一个临时Job起名test-recovery配置一个Execute shell构建步骤写echo Recovery OK保存后立即Build Now。如果构建成功且控制台输出正确证明整个认证链登录→鉴权→执行全部打通。注意如果Jenkins启用了CSRF保护默认开启某些API调用需要crumb但Web界面操作不受影响所以这三个动作足够覆盖99%的场景。4. Docker专项避坑指南卷挂载、权限、镜像层的三重陷阱实录4.1 卷挂载的四种模式与真实故障复现Docker环境下-v参数的写法直接决定生死。我把常见模式按风险等级排序高危模式-v /host/path:/var/jenkins_home无修饰符故障场景宿主机/host/path目录属主是root:root容器内Jenkins以UID 1001运行导致/var/jenkins_home/config.xml不可写。现象重启后配置还原日志报java.io.IOException: Permission denied。解决方案sudo chown -R 1001:1001 /host/path。中危模式-v /host/path:/var/jenkins_home:ro只读故障场景你以为挂载是为了读配置但Jenkins启动时需要写nodes/、jobs/等子目录。现象容器启动失败日志报Failed to create the home directory。解决方案删掉:ro或明确指定rw。低危模式-v /host/path:/var/jenkins_home:zSELinux上下文故障场景CentOS/RHEL系统启用SELinuxz标签让容器进程获得读写权限但宿主机目录若已有其他SELinux上下文如system_u:object_r:etc_t:s0会冲突。现象容器启动成功但config.xml修改不生效。解决方案sudo semanage fcontext -a -t container_file_t /host/path(/.*)? sudo restorecon -R /host/path。推荐模式-v jenkins-data:/var/jenkins_home命名卷优势Docker自动管理权限无需手动chown卷升级时配置不丢失。命令docker volume create jenkins-data docker run -v jenkins-data:/var/jenkins_home -p 8080:8080 jenkins/jenkins:lts。4.2 Docker Compose中的隐性陷阱environment与volumes的时序战争docker-compose.yml里这两行看似平平无奇却是线上事故高发区environment: - JAVA_OPTS-Djenkins.home/var/jenkins_home volumes: - ./jenkins-data:/var/jenkins_home问题在于JAVA_OPTS在容器启动时生效而volumes挂载是Docker守护进程做的。如果./jenkins-data目录不存在Docker会自动创建它但创建的属主是执行docker-compose up的用户比如ubuntu而不是Jenkins需要的UID 1001。结果就是容器内进程无法写入。解决方案只有两个启动前手动创建并赋权mkdir -p ./jenkins-data sudo chown -R 1001:1001 ./jenkins-data。在docker-compose.yml里用init容器预处理services: jenkins: image: jenkins/jenkins:lts volumes: - jenkins-data:/var/jenkins_home # 其他配置... volumes: jenkins-data: driver_opts: type: none device: /path/on/host o: bind然后用docker volume inspect jenkins-data确认挂载点再sudo chown 1001:1001 /path/on/host。4.3 镜像层覆盖为什么你改了config.xml重启后还是旧的Jenkins官方镜像jenkins/jenkins:lts的Dockerfile里有这么一行COPY init.groovy /usr/share/jenkins/ref/init.groovy这个init.groovy脚本会在容器首次启动时把/usr/share/jenkins/ref/下的默认配置包括config.xml复制到/var/jenkins_home。关键点这个复制只发生一次在容器第一次启动时。所以如果你的/var/jenkins_home挂载卷是空的复制就会发生如果卷里已有文件复制被跳过。但很多人不知道docker-compose down -v会删除命名卷下次up又变空卷触发复制覆盖你的修改。解决方案在/usr/share/jenkins/ref/目录下放一个自定义config.xml让它成为“新默认”。操作步骤docker run -d --name temp jenkins/jenkins:ltsdocker cp temp:/usr/share/jenkins/ref/config.xml ./ref-config.xml编辑./ref-config.xml加入你的管理员用户和权限构建自定义镜像FROM jenkins/jenkins:lts COPY ./ref-config.xml /usr/share/jenkins/ref/config.xmldocker build -t my-jenkins . docker run -v jenkins-data:/var/jenkins_home -p 8080:8080 my-jenkins这样无论卷是否为空新镜像都会提供你预设的配置。5. 常见问题速查表与独家排错技巧那些文档里不会写的血泪经验问题现象可能原因排查命令终极解决方案重启后密码无效日志报Failed to load config.xmlXML语法错误如未闭合标签、特殊字符未转义xmllint --noout $JENKINS_HOME/config.xml用备份文件恢复用vim的:set ftxml开启语法高亮或在线XML验证器校验登录成功但首页空白Console报403authorizationStrategy未赋予用户权限或denyAnonymousReadAccesstrue但用户不在权限列表grep -A 5 -B 5 authorizationStrategy $JENKINS_HOME/config.xml确保permission节点包含目标用户名且denyAnonymousReadAccess设为trueDocker容器启动后config.xml自动还原挂载卷为空触发镜像默认配置复制docker exec -it container ls -l /var/jenkins_home/config.xml对比宿主机文件时间戳执行touch /host/path/config.xml创建空文件阻止复制或用自定义镜像输入正确密码页面卡在“正在登录…”enableCaptchatrue但$JENKINS_HOME/captcha/目录权限错误ls -ld $JENKINS_HOME/captchachown -R 1001:1001 $JENKINS_HOME/captcha或临时设enableCaptchafalse用新密码登录提示“用户不存在”id节点值与登录用户名不一致大小写、空格grep -A 3 id $JENKINS_HOME/config.xml严格按Jenkins用户管理页显示的用户名填写用cat $JENKINS_HOME/users/*/config.xml | grep id交叉验证实操心得我总结出一个“三分钟诊断法”——当问题发生立刻执行三个命令docker ps -a \| grep jenkins看容器状态ExitedUpdocker logs container_name \| tail -20看最后20行错误docker exec -it container_name ls -l $JENKINS_HOME/config.xml看文件时间戳和权限90%的问题靠这三行命令就能定位到根源。别一上来就谷歌先让机器告诉你发生了什么。注意所有操作必须在维护窗口期进行避免影响CI/CD流水线。如果Jenkins是高可用集群务必逐台操作并确认主节点Master的配置同步机制如使用Shared File System或Database-backed persistence。6. 安全加固建议重置密码只是开始真正的防线在这里重置密码解决了燃眉之急但如果不做后续加固同样的问题三个月后还会找上门。我给客户的标准化加固清单强制启用API Token在Manage Jenkins → Configure Global Security里勾选Prevent Cross Site Request Forgery exploits并禁用Allow anonymous read access。所有自动化脚本如GitLab webhook、CLI调用改用API Token而不是明文密码。Token在用户Configure → API Token页生成有效期可设泄露后一键废止。配置审计日志安装Audit Trail Plugin设置Manage Jenkins → Audit Trail记录所有登录、配置修改、Job操作。日志存到ELK栈设置告警规则count by user where event login_failed 5 in last 1h。Docker镜像签名用cosign对自定义Jenkins镜像签名K8s集群里配置Policy Controller只允许运行已签名镜像杜绝恶意镜像注入。命令cosign sign -key cosign.key my-jenkins:latest。密码轮换自动化写个Python脚本每月1号用Jenkins CLI生成新哈希更新config.xml触发curl -X POST http://localhost:8080/reload重载配置。脚本放在$JENKINS_HOME/init.groovy.d/下随Jenkins启动自动执行。最后分享一个血泪教训某次我帮客户重置密码顺手把disableSignuptrue/disableSignup改成false想方便他们后续加用户。结果第二天发现Jenkins暴露在公网的端口被扫描器盯上自动注册了200多个垃圾用户占满内存OOM。从此我的加固清单第一条就是永远不要打开disableSignup除非你同时配置了IP白名单或反向代理的认证网关。安全不是功能开关而是层层嵌套的防御纵深。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

MindSpore Transformers LLM预训练全流程与调优实践 2026/10/2 11:00:51

MindSpore Transformers LLM预训练全流程与调优实践

从去年下半年开始,我不止一次被同事问到同一个问题:MindSpore到底能不能正经跑LLM预训练?问的人多了,我发现大家潜意识里还是把“大模型训练”和“PyTorch麒麟臂显卡”绑在一起,MindSpore被默认为只能在昇腾上跑跑推理…

阅读更多 →
2026深度学习全栈五要素:PINN、Transformer、GNN、强化学习与扩散模型实战解析 2026/10/2 11:00:51

2026深度学习全栈五要素:PINN、Transformer、GNN、强化学习与扩散模型实战解析

1. 为什么是这五块拼图:2026年深度学习能力地图先说实话:2026年还只盯着CNN或者单跑一张ResNet,确实有点不够用了。“全栈”这个词这两年被用烂了,但在深度学习这边,它指的是一种能力结构——你不仅仅会训模型&#xf…

阅读更多 →
大模型读出端Jev:从隐藏状态直达决策,绕过文本生成的工程实践 2026/10/2 11:00:45

大模型读出端Jev:从隐藏状态直达决策,绕过文本生成的工程实践

最近在调一个内部Agent工具调用链路时,我盯着日志里那个让人哭笑不得的片段看了很久:模型为了返回一个“发送邮件”的动作,先写了一段“好的,我这就帮你发送邮件”,然后生成了一长串JSON,最后还因为JSON尾部…

阅读更多 →
eNSP错误40排查全攻略:VirtualBox虚拟化环境修复指南 2026/10/2 11:00:45

eNSP错误40排查全攻略:VirtualBox虚拟化环境修复指南

1. 错误40的真相:先分清是eNSP的锅还是VirtualBox的锅 1.1 错误代码40到底从哪冒出来的 如果你在华为eNSP里启动AR1路由器或者USG6000V防火墙时,界面弹出“错误代码:40”,先别急着重装eNSP。这个错误绝大多数情况下并不是eNSP本身…

阅读更多 →
KEIL5 Debug完全指南:从断点单步到HardFault排查 2026/10/2 11:00:45

KEIL5 Debug完全指南:从断点单步到HardFault排查

1. 先说个真实场景:当“三板斧”失灵,Debug才是救命稻草 前阵子帮朋友调一块STM32F103的板子,现象很诡异:程序上电后偶尔能跑,偶尔卡死在某个中断里。他习惯用老办法——在代码里到处塞printf,串口打印“跑…

阅读更多 →
Word与WPS页眉页码设置全攻略:从分节到域代码,解决排版难题 2026/10/2 11:00:45

Word与WPS页眉页码设置全攻略:从分节到域代码,解决排版难题

1. 快速上手:Word/WPS页眉与页码的基础设置先说个有意思的现象。我帮人处理文档排版时,十个人里有八个觉得页眉页码是“小事一桩”,结果真上手一调,不是页眉横线删不掉,就是页码从第三页开始编号,折腾半小时…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉