针对本地SASL的Java身份验证

时间:2018-12-14 10:58:11

标签: java authentication pam sasl

我正在尝试创建一个Java类,以便根据本地SASL对用户进行身份验证。我的saslauthd配置是这样的:

$ cat /etc/sysconfig/saslauthd
# Directory in which to place saslauthd's listening socket, pid file, and so
# on.  This directory must already exist.
SOCKETDIR=/run/saslauthd

# Mechanism to use when checking passwords.  Run "saslauthd -v" to get a list
# of which mechanism your installation was compiled with the ablity to use.
MECH=pam

# Additional flags to pass to saslauthd on the command line.  See saslauthd(8)
# for the list of accepted flags.
FLAGS="-t 1"

基本上,它重定向针对PAM的身份验证。因此,例如,如果我正在做这样的测试。

testsaslauthd -s login -u <user> -p <password>
0: OK "Success."

一切正常。

我现在想通过Java管理这种机制,所以我编译了如下代码:

import java.util.Arrays;
import java.util.List;
import java.io.*;

public class PamAuthenticator {

    public static void main(String args[]) {

        String s = null;

        try {

            Process p = Runtime.getRuntime().exec("testsaslauthd -s "+args[2]+" -u "+args[0]+" -p "+args[1]);

            BufferedReader stdInput = new BufferedReader(new
                InputStreamReader(p.getInputStream()));

            BufferedReader stdError = new BufferedReader(new
                InputStreamReader(p.getErrorStream()));

            while ((s = stdInput.readLine()) != null) {
                System.out.println(s);
            }

            while ((s = stdError.readLine()) != null) {
                System.out.println(s);
            }

            System.exit(0);
        }
        catch (IOException e) {
            System.out.println("Exception: ");
            e.printStackTrace();
            System.exit(-1);
        }
    }

}

这正常工作:

$ java -cp .:* PamAuthenticator <user> <password> login
0: OK "Success."

我的问题是我不想执行testsaslauthd命令,因为这只是一个测试命令。为了尝试使用Java进行SASL身份验证,我可以做些更好且更聪明的事情吗?

1 个答案:

答案 0 :(得分:0)

您处在正确的轨道上,不要使用上面的代码。除了作为测试解决方案之外,它还会带来严重的安全性问题:command injection

Java 1.6中有一个名为SaslClient的接口。这正是您需要的。 example版本的JDK8

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.sasl.Sasl;
import javax.security.sasl.SaslClient;
import javax.security.sasl.SaslException;
import java.util.HashMap;

public class Test {
    public static void main(String[] args) throws SaslException {
        String userName = "username";
        String password = "password";
        SaslClient saslClient = Sasl.createSaslClient(new String[]{"PLAIN"},
                null, null, null, new HashMap<>(), callbacks -> {
                    for (final Callback callback : callbacks) {
                        if (callback instanceof NameCallback) {
                            NameCallback.class.cast(callback).setName(userName);
                            continue;
                        }
                        if (callback instanceof PasswordCallback) {
                            PasswordCallback.class.cast(callback).setPassword(password.toCharArray());
                            continue;
                        }
                        throw new UnsupportedCallbackException(callback);
                    }
                });
    }
}

当然,您应该更改用户名和密码的来源。