有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

bash如何在Java程序中检查Unix凭据

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

我考虑运行sudobash命令在Java代码中进行身份验证,并查看执行的命令的exit值是否等于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) 个答案

  1. # 1 楼答案

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

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

  2. # 2 楼答案

    基于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函数,它们也可以做同样的事情

    参考文献