在java中实现Kerberos身份验证

时间:2017-04-03 14:00:07

标签: java kerberos spnego

我们的客户端在linux机器上部署了一个tomcat应用程序,该应用程序将调用其网络外部的Web服务。直到现在它工作正常。但是现在,客户已经在他的服务器中安装了Kerberos。现在,我们需要在java代码中实现Kerberos身份验证。为了进行测试,我们给出了以下独立的java程序,以便在他们的环境中执行。

public class testauthproxy {

/**
 * Uses HttpClient 4.3.4 and CommonsIO 2.4
 */

public static void main(String[] args) throws FileNotFoundException,
        IOException {           
        testProxyAuthentication("URL");
}

public static void testProxyAuthentication(String url) throws FileNotFoundException, IOException {      
    boolean skipPortAtKerberosDatabaseLookup = true;
    try {
        File loginConfig = createLoginConf();

        System.out.println("Created config '" + loginConfig.getAbsolutePath() + "':");
        System.out.println(IOUtils.toString(new FileReader(loginConfig)));

        System.setProperty("java.security.auth.login.config", loginConfig.toURI().toString());
        System.setProperty("java.security.krb5.conf", "/etc/krb5.conf");
        System.setProperty("sun.security.krb5.debug", "true");
        System.setProperty("javax.security.auth.useSubjectCredsOnly",
                "false");

                Registry<AuthSchemeProvider> authSchemeRegistry = RegistryBuilder
                .<AuthSchemeProvider> create()
                .register(AuthSchemes.SPNEGO,
                        new SPNegoSchemeFactory(
                                skipPortAtKerberosDatabaseLookup)).build();

        CloseableHttpClient client = HttpClients.custom()
                .setDefaultAuthSchemeRegistry(authSchemeRegistry).build();
        HttpClientContext context = HttpClientContext.create();
        BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();

        // This may seem odd, but specifying 'null' as principal tells java
        // to use the logged in user's credentials
        Credentials useJaasCreds = new Credentials() {

            public String getPassword() {
                return null;
            }

            public Principal getUserPrincipal() {
                return null;
            }

        };
        credentialsProvider.setCredentials(new AuthScope(null, -1, null),
                useJaasCreds);
        context.setCredentialsProvider(credentialsProvider);

        HttpGet httpget = new HttpGet(url);
        CloseableHttpResponse response = client.execute(httpget, context);
        String responseString = IOUtils.toString(response.getEntity()
                .getContent());

        System.out.println("HTTP Response: Success");
        System.out.println(responseString);

    } catch (FileNotFoundException e) {
        System.out.println("Error Occurred: "+e.getMessage());
        e.printStackTrace();            
    } catch (IOException e) {
        e.printStackTrace();
        System.out.println("Error Occurred: "+e.getMessage());
    }catch(Exception e){
        e.printStackTrace();
        System.out.println("Error Occurred: "+e.getMessage());
    }
}

/**
 * Creates a temporary krb5.conf [libdefaults] default_realm = <domain>
 * 
 * [realms] snb.ch = { kdc = <kdc> admin_server = <kdc> }
 */
private static File createLoginConf()
        throws IOException {
    File tempFile = File.createTempFile("login", ".conf");
    ArrayList<String> lines = new ArrayList<String>();
    lines.add("com.sun.security.jgss.krb5.initiate {");     
    lines.add("\t\tcom.sun.security.auth.module.Krb5LoginModule required useTicketCache=true;");        
    lines.add("\t};");

    FileWriter writer = new FileWriter(tempFile);
    IOUtils.writeLines(lines, "\n", writer);
    IOUtils.closeQuietly(writer);
    return tempFile;
}
}

但是我们得到了连接超时错误。 krb5.conf文件路径是正确的,但是对于login.conf,我创建了一个临时文件并在运行时分配它。

我在互联网上搜索但无法获得任何解决方案。您能否建议是否有其他替代解决方案?

1 个答案:

答案 0 :(得分:0)

  

我们的客户在Linux机器上部署了一个tomcat应用程序,并且   该应用程序将调用其外部的Web服务   网络。到现在为止一切正常。但是现在,客户已经安装   服务器中的Kerberos。现在,我们需要实现Kerberos   Java代码中的身份验证。为了进行测试,我们给出了以下内容   在其环境中执行的独立Java程序。

据此我了解到,您的客户端与应用程序不在同一个域中。

跨不同域requires some more hoops的Kerberos。

简而言之,两个域都必须连接到父域,并且父域将是发出票证的域。子域为客户提供了可用于从父域获取票证的引荐票证,但是必须设置父域以颁发Kerberos票证。