chage 是 Linux 中强制用户定期改密最直接有效的方法,通过为每个用户单独设置策略实现;/etc/login.defs 中的配置仅对新用户生效,老用户需手动用 chage 配置,如 chage -M 90 username 和 chage -d 0 username。

Linux 系统中 chage 设置密码过期最直接有效
强制用户定期改密,核心不是改配置文件,而是用 chage 给每个用户设策略。系统级配置(如 /etc/login.defs 中的 PASS_MAX_DAYS)只对新用户生效,老用户不会自动继承。
-
chage -M 90 username:设置用户密码 90 天后过期 -
chage -d 0 username:下次登录强制修改密码(-d 0 表示“最后修改日期为 Unix 时间零点”,即已过期) - 批量操作可配合
getent passwd和while read,但注意避开系统账户(UID - 执行后用户首次登录会看到
You are required to change your password immediately提示,不能跳过
OpenLDAP 中 pwdMaxAge 配置不生效的常见原因
LDAP 密码策略(PPolicy)里设了 pwdMaxAge,但客户端没反应?大概率是策略没绑定到用户、或客户端不支持 PPolicy 扩展协议。
- 必须通过
pwdPolicySubentry属性把策略条目显式挂到用户节点下,不能只靠 OU 继承 - 客户端(如 Linux PAM 的
pam_ldap.so)需启用ppolicy选项,否则只走基础密码校验 -
pwdMaxAge单位是秒,填2592000才是 30 天,别误写成天数 - 测试时用
ldapwhoami -Y EXTERNAL -H ldapi:///看是否返回passwordExpired或passwordWarning响应
Web 应用层绕过系统限制的典型漏洞点
即使 chage 设了 90 天过期,只要 Web 登录接口没校验 shadow 中的 passwd_max_days 和 passwd_last_change,用户就能无限续期。
- PHP/Python 调用
auth_pam时,默认不触发密码过期检查,得手动调pam_acct_mgmt() - Spring Security 的
LdapAuthenticationProvider默认不读 PPolicy 响应,需自定义LdapUserDetailsMapper解析pwdChangedTime - 若应用自己存密码哈希(非透传系统认证),那
chage完全无效——此时必须在业务逻辑里维护password_expire_at字段并拦截登录
Ansible 自动化部署时 user 模块和 community.general.chage 的区别
用 Ansible 批量设密码策略,别只用 user 模块的 expires 参数——它控制的是账户禁用时间,不是密码过期。
-
user模块的expires对应/etc/shadow第 8 字段(account expiration),和密码无关 - 必须用
community.general.chage模块(或原生command调chage)才能写第 5 字段(max_days) - Playbook 中要加
become: true,且目标机器得装chage(某些 Alpine 镜像默认不带) - 若用
shell: chage -M 60 {{ item }},记得加args: executable: /bin/bash,避免 dash 下语法报错
真正难的不是设参数,是确认所有路径都被覆盖:SSH 登录、SFTP、Web 控制台、API Token 认证……只要有一处漏掉密码过期检查,策略就形同虚设。










