Spring Boot如何无需su权限校验Unix/Linux系统用户凭证
现有实现问题
你当前的su调用方案存在多处不可靠和安全风险:
- 主流发行版的
su命令默认从tty终端读取密码,不接受标准输入传入的密码,你的代码在大部分环境下会直接验证失败 - 每次验证都需要创建子进程,性能极低,高并发场景下完全不可用
- 密码以明文形式写入进程输入流,存在被进程监听、泄露的风险
- 服务进程需要较高的运行权限,扩大攻击面
无su权限的最优实现方案
优先推荐使用Linux原生的PAM(可插拔认证模块)完成系统用户校验,这是所有Linux发行版统一的标准认证接口,不需要调用su,也不需要服务以root权限运行。
实现步骤
- 先安装PAM的Java绑定依赖,推荐使用
libpam4j,无需额外安装系统依赖,兼容性好 - 新增PAM配置文件
/etc/pam.d/spring-auth,内容如下:
auth required pam_unix.so account required pam_unix.so
- Java代码示例:
import org.jvnet.libpam.PAM; import org.jvnet.libpam.PAMException; import org.jvnet.libpam.UnixUser; public class AuthenticationService { public boolean authenticate(String username, String password) { try { PAM pam = new PAM("spring-auth"); UnixUser user = pam.authenticate(username, password); // 验证成功,可按需获取用户的uid、gid、所属组等信息 pam.dispose(); return true; } catch (PAMException e) { // 验证失败,可按需打印日志,不要输出密码 return false; } } }
其他可选方案
如果不想引入PAM依赖,也可以选择以下方案,但安全性和便捷性低于PAM方案:
- 给运行服务的用户授予
shadow用户组权限,读取/etc/shadow中的加密哈希,手动对用户输入的密码做哈希比对。注意该方案要求服务进程有读shadow文件的权限,一旦服务被攻破会导致系统所有用户的密码哈希泄露,风险极高 - 调用
sshpass配合ssh localhost做验证,但性能和安全都不如PAM方案,不推荐
安全建议
- 所有前端传入的密码必须走HTTPS加密传输,禁止明文传输
- 不要在任何日志、堆栈信息中输出用户密码内容
- 服务进程用普通权限用户运行即可,不需要root权限,PAM验证不需要高权限
- 可以直接复用PAM自带的
pam_tally2、pam_faildelay模块实现登录失败锁定、延迟返回等防暴力破解功能,无需自行开发
内容的提问来源于stack exchange,提问作者Luca
相关产品推荐
相关产品推荐

