1. 程式人生 > >HttpClient+NTLM認證

HttpClient+NTLM認證

1.HttpClient的使用步驟

1)建立HttpClient物件(專案中之前用的是CloseableHttpClient,這個物件無法使用NTLM認證,我換成了DefaultHttpClient)

2)建立請求方法的例項,並指定URL,根據請求方式的不同建立HttpGet或HttpPOST請求

3)如果需要傳送請求引數,可以呼叫HttpGet/HttpPost共同的setParams(HetpParams params)方法來實現,對於HttpPost物件而言,也可呼叫setEntity(HttpEntity entity)方法來設定請求引數。

4)呼叫HttpClient物件的execute(HttpUriRequest request)傳送請求,該方法返回一個HttpResponse。

5. 呼叫HttpResponse的getAllHeaders()、getHeaders(String name)等方法可獲取伺服器的響應頭;呼叫HttpResponse的getEntity()方法可獲取HttpEntity物件,該物件包裝了伺服器的響應內容。程式可通過該物件獲取伺服器的響應內容。

6. 釋放連線。無論執行方法是否成功,都必須釋放連線

2.專案中用到的工具類

@Component
public class HttpConnectionManager {


    private static final Integer DEFAULT_MAX_TOTAL = 200;
    private static final Integer DEFAULT_MAX_PER_ROUTE = 20;




    private final Logger logger = LoggerFactory.getLogger(getClass());


    private PoolingHttpClientConnectionManager cm;
    private Registry<ConnectionSocketFactory> registry;
    private ApplicationProperties applicationProperties;


    private void init() {
        try {
            SSLContextBuilder builder = SSLContexts.custom();

            builder.loadTrustMaterial(null, (chain, authType) -> true);
            SSLContext sslContext = builder.build();
            SSLConnectionSocketFactory sslSF = new SSLConnectionSocketFactory(
                    sslContext, new String[] { Constants.TLS_V1_PROTOCAL, Constants.SSL_V3_PROTOCAL}, null,
                    NoopHostnameVerifier.INSTANCE);


            registry = RegistryBuilder
                    .<ConnectionSocketFactory> create()
                    .register(Constants.HTTP_PROTOCAL, PlainConnectionSocketFactory.INSTANCE)
                    .register(Constants.HTTPS_PROTOCAL, sslSF)
                    .build();


            cm = new PoolingHttpClientConnectionManager(registry);
            cm.setMaxTotal(DEFAULT_MAX_TOTAL);
            cm.setDefaultMaxPerRoute(DEFAULT_MAX_PER_ROUTE);


        } catch (Exception ex) {
            logger.error("Can't initialize connection manager! Exiting");
            System.exit(FATAL_EXIT_CODE);
        }
    }


    public HttpConnectionManager(ApplicationProperties applicationProperties) {
        init();
        this.applicationProperties = applicationProperties;
    }

  //這裡是我們專案對請求的一個封裝,這裡請求的URL配置在application.properties中

    public HttpPost defaultProxiedPostRequest(String url, String jsonStr) throws UnsupportedEncodingException {
        if (StringUtils.isBlank(url) || StringUtils.isBlank(jsonStr)) {
            throw new InvalidParameterException("Invalid url or requestJson");
        }


        HttpPost request = new HttpPost(url);
        StringEntity se = new StringEntity(jsonStr);
        request.setEntity(se);
        request.setHeader("Accept", "application/json");
        request.setHeader("Content-type", "application/json");
        if (StringUtils.isNotBlank(applicationProperties.getHrgenieHttpProxyHost())) {
            HttpHost proxy = new HttpHost(applicationProperties.getHrgenieHttpProxyHost(), applicationProperties.getHrgenieHttpProxyPort());
            RequestConfig config = RequestConfig.custom().setProxy(proxy).build();
            request.setConfig(config);
        }
        return request;
    }

   //獲取到HttpClient物件

    public CloseableHttpClient getConnection() {
        CloseableHttpClient httpclient = HttpClients.custom().setConnectionManager(cm).build();
        return httpclient;
    }

}

3.使用HttpClient加入NTLM驗證的核心程式碼

       @SuppressWarnings("deprecation")
public <V, K> V search(K k, Class<V> respClz) {
        String snqUrl = applicationProperties.getSinequa().getUrl();
        Optional<String> reqJson = SearchEngineUtil.objToJson(k);
        HttpPost postReq = null;

        try {

           //利用上面的類對請求做封裝

            postReq = httpConnectionManager.defaultProxiedPostRequest(snqUrl, reqJson.get());
        } catch (IOException ex) {
            logger.error("Exception thrown when getting request, exception is:{}", ex);
            throw new BadSearchEngineRequestException("Invalid SINEQUA search request!");
        }


        V snqResponse = null;
        //新建一個NTLM物件,前面兩個引數是用於驗證的使用者名稱和密碼
        NTCredentials creds = new NTCredentials(userAu, passAu,"", "");
        // 新建一個httpclient物件,把NTLM驗證加入該物件
        DefaultHttpClient httpclient = new DefaultHttpClient();
        httpclient.getCredentialsProvider().setCredentials(AuthScope.ANY, creds);
        
        try (CloseableHttpResponse response = httpclient.execute(postReq)) {
            snqResponse = parseResponse(response, respClz);
        } catch (IOException ex) {
            logger.error("Exception thrown when getting the response, exception is:{}", ex);
            throw new BadSearchEngineResponseException("Invalid SINEQUA search response!");
        }
        return snqResponse;

    }

附加:(用於物件和Json之間相互轉換的工具類)

public class SearchEngineUtil {


    public static Optional<String> objToJson(Object object) {
        ObjectMapper mapper = new ObjectMapper();
        String jsonStr = null;
        try {
            jsonStr = mapper.writeValueAsString(object);
        } catch (JsonProcessingException ex) {
            ex.printStackTrace();
        }
        return Optional.ofNullable(jsonStr);
    }


    public static <T> Optional<T> jsonToObj(String json, Class<T> clz) {
        ObjectMapper mapper = new ObjectMapper();
        T objToRet = null;
        try {
            objToRet = mapper.readValue(json, clz);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        return Optional.ofNullable(objToRet);
    }
}