developers world

tecnical questionjava

HttpClient

Java and HTTP NTLM(v2) authentication with HttpClient

0Hancock posted on 2024/04/12 16:07:08

/*
Dependencies:

HttpClient v4.5.14
https://dlcdn.apache.org//httpcomponents/httpclient/binary/httpcomponents-client-4.5.14-bin.zip

JCIFS v1.3.19
https://www.jcifs.org/src/jcifs-1.3.19.zip
*/

package com.example;
import java.io.*;
import java.util.*;


import org.apache.http.*;
import org.apache.http.auth.*;
import org.apache.http.client.*;
import org.apache.http.client.config.*;
import org.apache.http.client.methods.*;
import org.apache.http.config.*;
import org.apache.http.impl.auth.*;
import org.apache.http.impl.client.*;
import org.apache.http.message.*;
import org.apache.http.protocol.*;
import org.apache.http.util.*;


import jcifs.ntlmssp.*;
import jcifs.util.Base64;



public class SampleClient {
public static void main (String args []) throws Exception {
System.out.println("Hello World");
Registry<AuthSchemeProvider> authSchemeRegistry = RegistryBuilder.<AuthSchemeProvider>create()
.register(AuthSchemes.NTLM, new JCIFSNTLMSchemeFactory())
      .register(AuthSchemes.SPNEGO, new SPNegoSchemeFactory())
      .build();
RequestConfig config = RequestConfig.custom()
    .setTargetPreferredAuthSchemes(Arrays.asList(AuthSchemes.NTLM ,AuthSchemes.SPNEGO))
    .build();

CredentialsProvider credsProvider = new BasicCredentialsProvider();
        credsProvider.setCredentials(AuthScope.ANY,
                new NTCredentials(user, password, null, domain));

        CloseableHttpClient httpclient = HttpClients.custom()
              .setDefaultAuthSchemeRegistry(authSchemeRegistry)
              .setDefaultCredentialsProvider(credsProvider)
              .setDefaultRequestConfig(config)
              .build();
        try {
            /*
             HttpPost request = new HttpPost(url);
        StringEntity input = new StringEntity(payLoad);
        input.setContentType("application/json");
        request.setEntity(input);
             */
        HttpGet request = new HttpGet(url);
       
            System.out.println("Executing request " + request.getRequestLine());
            CloseableHttpResponse response = httpclient.execute(request);
            try {
                System.out.println("----------------------------------------");
                System.out.println(response.getStatusLine());
                System.out.println(EntityUtils.toString(response.getEntity()));
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }
        
}
}
class JCIFSNTLMSchemeFactory implements AuthSchemeProvider {

@Override
    public AuthScheme create(final HttpContext context) {
return new SpNegoNTLMScheme(new JCIFSEngine());
    }
}
class JCIFSEngine implements NTLMEngine {

    private static final int TYPE_1_FLAGS = 
            NtlmFlags.NTLMSSP_NEGOTIATE_56 | 
            NtlmFlags.NTLMSSP_NEGOTIATE_128 | 
            NtlmFlags.NTLMSSP_NEGOTIATE_NTLM2 | 
            NtlmFlags.NTLMSSP_NEGOTIATE_ALWAYS_SIGN | 
            NtlmFlags.NTLMSSP_REQUEST_TARGET;

    public String generateType1Msg(final String domain, final String workstation)
            throws NTLMEngineException {
        final Type1Message type1Message = new Type1Message(TYPE_1_FLAGS, domain, workstation);
        return Base64.encode(type1Message.toByteArray());
    }

    public String generateType3Msg(final String username, final String password,
            final String domain, final String workstation, final String challenge)
            throws NTLMEngineException {
        Type2Message type2Message;
        try {
            type2Message = new Type2Message(Base64.decode(challenge));//debug
        } catch (final IOException exception) {
            throw new NTLMEngineException("Invalid NTLM type 2 message", exception);
        }
        final int type2Flags = type2Message.getFlags();
        final int type3Flags = type2Flags
                & (0xffffffff ^ (NtlmFlags.NTLMSSP_TARGET_TYPE_DOMAIN | NtlmFlags.NTLMSSP_TARGET_TYPE_SERVER));
        final Type3Message type3Message = new Type3Message(type2Message, password, domain,
                username, workstation, type3Flags);
        return Base64.encode(type3Message.toByteArray());
    }

}

/**
 * Based on {@link NTLMScheme}
 * @author m.oberwasserlechner@mum-software.com
 *
 */
class SpNegoNTLMScheme extends AuthSchemeBase {

  enum State {
    UNINITIATED,
    CHALLENGE_RECEIVED,
    MSG_TYPE1_GENERATED,
    MSG_TYPE2_RECEVIED,
    MSG_TYPE3_GENERATED,
    FAILED,
  }

  private final NTLMEngine engine;

  private State state;
  private String challenge;

  public SpNegoNTLMScheme(final NTLMEngine engine) {
    super();
    if (engine == null) {
      throw new IllegalArgumentException("NTLM engine may not be null");
    }
    this.engine = engine;
    this.state = State.UNINITIATED;
    this.challenge = null;
  }

  @Override
  public String getSchemeName() {
  return "ntlm";
  }

  public String getParameter(String name) {
    // String parameters not supported
    return null;
  }

  public String getRealm() {
    // NTLM does not support the concept of an authentication realm
    return null;
  }

  public boolean isConnectionBased() {
    return true;
  }

  @Override
  protected void parseChallenge(
      final CharArrayBuffer buffer,
      int beginIndex, int endIndex) throws MalformedChallengeException {
    String challenge = buffer.substringTrimmed(beginIndex, endIndex);
    if (challenge.length() == 0) {
      if (this.state == State.UNINITIATED) {
        this.state = State.CHALLENGE_RECEIVED;
      } else {
        this.state = State.FAILED;
      }
      this.challenge = null;
    } else {
      this.state = State.MSG_TYPE2_RECEVIED;
      this.challenge = challenge;
    }
  }
  
  public Header authenticate(final Credentials credentials, final HttpRequest request) throws AuthenticationException {
    NTCredentials ntcredentials = null;
    
    try {
    Thread.sleep(500);//nhadh: wait to make it work
      ntcredentials = (NTCredentials) credentials;//debug
    } catch (ClassCastException e) {
      throw new InvalidCredentialsException(
          "Credentials cannot be used for NTLM authentication: "
              + credentials.getClass().getName());
    }
    catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}

    String response = null;
    if (this.state == State.CHALLENGE_RECEIVED || this.state == State.FAILED) {
      response = this.engine.generateType1Msg(
          ntcredentials.getDomain(),
          ntcredentials.getWorkstation());
      this.state = State.MSG_TYPE1_GENERATED;
    } else if (this.state == State.MSG_TYPE2_RECEVIED) {
      response = this.engine.generateType3Msg(
          ntcredentials.getUserName(),
          ntcredentials.getPassword(),
          ntcredentials.getDomain(),
          ntcredentials.getWorkstation(),
          this.challenge);
      this.state = State.MSG_TYPE3_GENERATED;
    } else {
      throw new AuthenticationException("Unexpected state: " + this.state);
    }

    CharArrayBuffer buffer = new CharArrayBuffer(32);
    if (isProxy()) {
      buffer.append(AUTH.PROXY_AUTH_RESP);
    } else {
      buffer.append(AUTH.WWW_AUTH_RESP);
    }
    buffer.append(": ");
    buffer.append(getSchemeName().toUpperCase());
    buffer.append(" ");
    buffer.append(response);
    return new BufferedHeader(buffer);
  }

  public boolean isComplete() {
    return this.state == State.MSG_TYPE3_GENERATED || this.state == State.FAILED;
  }

}

java
HttpClient

Comments

There is no comment
Contact: