2012-03-27 24 views
5

Sto scrivendo una connessione HTTP con autenticazione Kerberos. Ho "HTTP/1.1 401 non autorizzato". Potresti raccomandarmi cosa dovrei controllare? Penso che ci sia qualche trucco, ma non lo vedo.Connessione Kerberos tramite client HTTP

Potrebbe essere necessario impostare l'intestazione "WWW-Authenticate" con "Negoziare"?

Grazie mille in anticipo per qualsiasi aiuto e idee.

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(); 
     } 
    } 
} 
+0

Ho scritto una soluzione alternativa per questo problema qui: http://stackoverflow.com/a/22865583/381161 –

risposta

0

Ho avuto lo stesso problema e ho appena trovato il tuo post. L'ho inserito come segnalibro in modo da poter pubblicare una risposta quando l'ho riparato. Inserisco un link alla mia domanda a cui qualcuno ha risposto, quindi se qualcuno trova questo tramite Google, trova la risposta:

HttpClient ha problemi nel creare l'SPN per l'annuncio quando l'URL ha una porta.

Vedi la mia domanda + risposta qui: HttpClient check Kerberos secured webpage. NTLM login didn't work

3

SPNEGO non funzionerà perché si utilizza localhost come hostname URL.

Il server è configurato per un set di SPN (o almeno uno) che inizia con HTTP/ registrato nell'account del servizio ActiveDirectory. Puoi richiederli da AD grazie a setspn -l yourServiceAccount.

L'URL deve utilizzare un nome host del server efficace noto come SPN in ActiveDirectory in modo che Apache Http Client possa negoziare un TGS per questo servizio e inviarlo al server.

0

Ecco un client di prova che ho scritto nel mio progetto. Questo client si basa su tutti i tipi di crittografia da abilitare il JDK,

Se vedete seguente nei log e il vostro keytab vengono crittografati a etypes di default 256 bit per default_tkt_enctypes: 17 16 23 1 3.

poi seguendo vaso http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html necessità di essere scaricato e messo in JDK/jre/lib/security per abilitare la crittografia AES a 256 bit dopo che si dovrebbe vedere la seguente nei registri etypes default per default_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; 

classe Utility

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/[email protected]", 
       "file://C://Development//test.keytab", true); 
     HttpResponse response = restTest.callRestUrl("http://test.com/service/employees", 
       "HTTP/[email protected]"); 
     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")); 
    } 
}