Kerberos connection using HTTP client

I am writing an HTTP connection with Kerberos authentication. I have "HTTP / 1.1 401 Unauthorized". Could you recommend me what I should check? I think there is some kind of trick, but I do not see this.

Maybe I should set the header "WWW-Authenticate" with "Negotiate"?

Many thanks for the advanced approach for any help and ideas.

public class ClientKerberosAuthentication {

    public static void main(String[] args) throws Exception {

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

        DefaultHttpClient httpclient = new DefaultHttpClient();
        try {
           NegotiateSchemeFactory nsf = new NegotiateSchemeFactory();
           httpclient.getAuthSchemes().register(AuthPolicy.SPNEGO, nsf);            

           List<String> authpref = new ArrayList<String>();
           authpref.add(AuthPolicy.BASIC);
           authpref.add(AuthPolicy.SPNEGO);
           httpclient.getParams().setParameter(AuthPNames.PROXY_AUTH_PREF, authpref);            


           httpclient.getCredentialsProvider().setCredentials(
                  new AuthScope(null, -1, AuthScope.ANY_REALM, AuthPolicy.SPNEGO), 
                  new UsernamePasswordCredentials("myuser", "mypass"));            

           System.out.println("----------------------------------------");
           HttpUriRequest request = new HttpGet("http://localhost:8084/web-app/webdav/213/_test.docx");
           HttpResponse response = httpclient.execute(request);
           HttpEntity entity = response.getEntity();

           System.out.println("----------------------------------------");
           System.out.println(response.getStatusLine());
           System.out.println("----------------------------------------");
           if (entity != null) {
               System.out.println(EntityUtils.toString(entity));
           }
           System.out.println("----------------------------------------");

           // This ensures the connection gets released back to the manager
           EntityUtils.consume(entity);

        } finally {
           httpclient.getConnectionManager().shutdown();
        }
    }
}
+5
source share
3 answers

SPNEGO will not work because you use localhostURLs as the hostname.

SPN ( ), HTTP/, ActiveDirectory. AD setspn -l yourServiceAccount.

URL , SPN ActiveDirectory, Apache Http Client TGS .

+3

, . , , . , - , , - Google, :

HttpClient SPN AD, URL- .

. + : HttpClient - Kerberos. NTLM

0

Here is a test client that I wrote in my project. This client relies on all types of encryption to be included in the JDK.

If you see the following in your logs, and your keytab is encrypted using 256-bit standard steps for default_tkt_enctypes: 17 16 23 1 3.

then the following bank   http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html must be downloaded and placed in JDK/jre/lib/securityto enable AES256 encryption, after which you should see the following in the logs on default fordefault_tkt_enctypes: 18 17 16 23 1 3.

import java.io.IOException;
import java.io.InputStream;
import java.security.Principal;
import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;

import javax.security.auth.Subject;
import javax.security.auth.kerberos.KerberosPrincipal;
import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.Configuration;
import javax.security.auth.login.LoginContext;

import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthSchemeProvider;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.Credentials;
import org.apache.http.client.CookieStore;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.AuthSchemes;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.config.Lookup;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.impl.auth.SPNegoSchemeFactory;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.cookie.BasicClientCookie;

Utility class

public class KerberosHttpClient {
    private String principal;
    private String keyTabLocation;

    public KerberosHttpClient() {}
    public KerberosHttpClient(String principal, String keyTabLocation) {
        super();
        this.principal = principal;
        this.keyTabLocation = keyTabLocation;
    }

    public KerberosHttpClient(String principal, String keyTabLocation, String krb5Location) {
        this(principal, keyTabLocation);
        System.setProperty("java.security.krb5.conf", krb5Location);
    }

    public KerberosHttpClient(String principal, String keyTabLocation, boolean isDebug) {
        this(principal, keyTabLocation);
        if (isDebug) {
            System.setProperty("sun.security.spnego.debug", "true");
            System.setProperty("sun.security.krb5.debug", "true");
        }
    }

    public KerberosHttpClient(String principal, String keyTabLocation, String krb5Location, boolean isDebug) {
        this(principal, keyTabLocation, isDebug);        
        System.setProperty("java.security.krb5.conf", krb5Location);
    }

    private static HttpClient buildSpengoHttpClient() {
        HttpClientBuilder builder = HttpClientBuilder.create();            
        Lookup<AuthSchemeProvider> authSchemeRegistry = RegistryBuilder.<AuthSchemeProvider>create().
                register(AuthSchemes.SPNEGO, new SPNegoSchemeFactory(true)).build();
        builder.setDefaultAuthSchemeRegistry(authSchemeRegistry);
        BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(new AuthScope(null, -1, null), new Credentials() {
            @Override
            public Principal getUserPrincipal() {
                return null;
            }
            @Override
            public String getPassword() {
                return null;
            }
        });
        builder.setDefaultCredentialsProvider(credentialsProvider);        
        CloseableHttpClient httpClient = builder.build();
        return httpClient;
    }

    public HttpResponse callRestUrl(final String url,final String userId) {
        //keyTabLocation = keyTabLocation.substring("file://".length());
        System.out.println(String.format("Calling KerberosHttpClient %s %s %s",this.principal, this.keyTabLocation, url));
        Configuration config = new Configuration() {
            @SuppressWarnings("serial")
            @Override
            public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
                return new AppConfigurationEntry[] { new AppConfigurationEntry("com.sun.security.auth.module.Krb5LoginModule",
                        AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, new HashMap<String, Object>() {
                            {
                                put("useTicketCache", "false");
                                put("useKeyTab", "true");
                                put("keyTab", keyTabLocation);
                                //Krb5 in GSS API needs to be refreshed so it does not throw the error
                                //Specified version of key is not available
                                put("refreshKrb5Config", "true");
                                put("principal", principal);
                                put("storeKey", "true");
                                put("doNotPrompt", "true");
                                put("isInitiator", "true");
                                put("debug", "true");
                            }
                        }) };
            }
        };
        Set<Principal> princ = new HashSet<Principal>(1);
        princ.add(new KerberosPrincipal(userId));
        Subject sub = new Subject(false, princ, new HashSet<Object>(), new HashSet<Object>());
        try {
            LoginContext lc = new LoginContext("", sub, null, config);
            lc.login();
            Subject serviceSubject = lc.getSubject();
            return Subject.doAs(serviceSubject, new PrivilegedAction<HttpResponse>() {
                HttpResponse httpResponse = null;
                @Override
                public HttpResponse run() {
                    try {    
                        HttpUriRequest request = new HttpGet(url);
                        HttpClient spnegoHttpClient = buildSpengoHttpClient();
                        httpResponse = spnegoHttpClient.execute(request);
                                                return httpResponse;
                    } catch (IOException ioe) {
                        ioe.printStackTrace();
                    }
                    return httpResponse;
                }
            });
        } catch (Exception le) {
            le.printStackTrace();;
        }
        return null;
    }

    public static void main(String[] args) throws UnsupportedOperationException, IOException {
        KerberosHttpClient restTest = new KerberosHttpClient("HTTP/test@test.com",
                "file://C://Development//test.keytab", true);
        HttpResponse response = restTest.callRestUrl("http://test.com/service/employees",
                "HTTP/test@test.com");
        InputStream is = response.getEntity().getContent();
        System.out.println("Status code " + response.getStatusLine().getStatusCode());
        System.out.println(Arrays.deepToString(response.getAllHeaders()));
        System.out.println(new String(IOUtils.toByteArray(is), "UTF-8"));
    }
}
0
source

All Articles