如何检查Java程序中的Unix凭据

时间:2017-11-29 21:24:14

标签: java bash unix authentication sudo

我有两个代表用户的字符串和该用户的密码。我想在Unix环境中检查这是否是有效的身份验证对。

我考虑过运行sudo bash命令来验证Java代码内部,并查看执行的命令的退出值是否等于0.

但是我无法做到这一点。

public class Test{
    public static void main(String args[]){
        String user = "user";
        String pass = "pass\n";

        try{

            Process proc = new ProcessBuilder(
                "/bin/sh","-c","sudo","-S","su",user).start();

            OutputStream os = proc.getOutputStream();
            os.write(pass.getBytes());
            os.flush();
            os.close();

            try{
                System.out.println(proc.waitFor());
            } catch ( InterruptedException e ){
                e.printStackTrace();
            }

        } catch ( IOException e ){
            e.printStackTrace();
        }

    }
}

此代码打印1作为退出代码。 我真的尝试过我能在网上找到的所有内容,但我仍然需要弄清楚如何正常工作。

任何人都可以帮助我吗? THX

2 个答案:

答案 0 :(得分:0)

sudo询问当前用户的密码,即启动java进程的用户,因此不会检查user的密码。

而不是"/bin/sh","-c","sudo","-S","su",user).start();尝试"/bin/sh","-c","su",user).start();。这只会尝试切换到该用户,因此会询问user的密码。

答案 1 :(得分:0)

基于su.c源代码I've wrote a simple java program,使用JNA进行用户凭据验证。它必须适用于所有具有libc和crypt库的基于Unix的发行版,如下所示:

public static void main(String[] args) {
    final Scanner scanner = new Scanner(System.in);
    System.out.println("type the user");
    final String user = scanner.nextLine();

    System.out.println("type password");
    final String password = scanner.nextLine();

    System.out.println("RESULT\n===========================================");
    final SPassword passwd = CLibrary.INSTANCE.getspnam(user);
    if(passwd == null){
        throw new RuntimeException(String.valueOf(Native.getLastError()));
    }

    final String encrypted = Crypt.INSTANCE.crypt(password, passwd.sp_pwdp);
    System.out.printf("matches=%b%n", encrypted.equals(passwd.sp_pwdp));
}

interface Crypt extends Library {
    Crypt INSTANCE = Native.loadLibrary("crypt", Crypt.class);
    String crypt(String key, String salt);
}

interface CLibrary extends Library {
    CLibrary INSTANCE = Native.loadLibrary("c", CLibrary.class);
    Password getpwnam(String username);
    SPassword getspnam(String username);
}

测试

git clone https://github.com/mageddo/java-native-examples.git &&\
cd java-native-examples && git checkout -f ef4eb3e &&\
./gradlew clean build fatjar &&\
sudo java -jar build/libs/java-native-examples-all-*.jar

type the user
elvis
type password
*********
RESULT
===========================================
matches=true

Obs :缺点是这个应用程序必须以root或sudo用户身份运行,我无法解决这个问题,无论如何我认为一旦 su 命令就可以出于安全原因(如果在您的上下文中存在问题),我建议将此功能与应用程序隔离,然后通过REST,Soap,TCP等来调用它。这样,您当前的应用程序将不需要以root身份运行。

如果您愿意,可以用apache commons codec lib function替换执行相同操作的crypt函数。

参考