2014-01-19 3 views
9

나는이 같은 요청을 사용했다 : 파이Apache HttpClient에서 SSL 클라이언트 인증서를 사용하려면 어떻게해야합니까? 파이썬에서

requests.put(
       webdavURL, 
       auth=(tUsername, tPassword), 
       data=webdavFpb, 
       verify=False, 
       cert=("/path/to/file.pem", "/path/to/file.key")) 

쉽습니다.

이제 Apache HttpClient를 사용하여 Java에서 동일한 작업을 구현해야합니다. HttpClient를 사용하여 요청할 때 어떻게 클라이언트 인증서를 전달할 수 있습니까?

답변

7

자바의 주요 차이점은 키와 인증서를 보통 key store에 넣고 거기에서 사용하는 것입니다. 여러분이 언급 한 것처럼 사람들은 종종 httpcomponents client을 언급 한 것처럼 (파이썬 예제에서 requests library을 사용하는 것과 같이) 별도의 라이브러리를 사용하려고합니다. 여기

는 앞서 언급 한 라이브러리를 사용하여 키 저장소에서 클라이언트 인증서를 사용하는 예이다 :

import org.apache.http.HttpEntity; 
import org.apache.http.HttpResponse; 
import org.apache.http.client.HttpClient; 
import org.apache.http.client.methods.HttpGet; 
import org.apache.http.impl.client.HttpClients; 
import org.apache.http.ssl.SSLContexts; 
import org.apache.http.util.EntityUtils; 
import org.junit.Test; 

import javax.net.ssl.SSLContext; 
import java.io.InputStream; 
import java.security.KeyStore; 

import static org.junit.Assert.assertEquals; 
import static org.junit.Assert.assertNotNull; 

public class MyClientCertTest { 

    private static final String KEYSTOREPATH = "/clientkeystore.jks"; // or .p12 
    private static final String KEYSTOREPASS = "keystorepass"; 
    private static final String KEYPASS = "keypass"; 

    KeyStore readStore() throws Exception { 
     try (InputStream keyStoreStream = this.getClass().getResourceAsStream(KEYSTOREPATH)) { 
      KeyStore keyStore = KeyStore.getInstance("JKS"); // or "PKCS12" 
      keyStore.load(keyStoreStream, KEYSTOREPASS.toCharArray()); 
      return keyStore; 
     } 
    } 
    @Test 
    public void readKeyStore() throws Exception { 
     assertNotNull(readStore()); 
    } 
    @Test 
    public void performClientRequest() throws Exception { 
     SSLContext sslContext = SSLContexts.custom() 
       .loadKeyMaterial(readStore(), KEYPASS.toCharArray()) // use null as second param if you don't have a separate key password 
       .build(); 

     HttpClient httpClient = HttpClients.custom().setSSLContext(sslContext).build(); 
     HttpResponse response = httpClient.execute(new HttpGet("https://slsh.iki.fi/client-certificate/protected/")); 
     assertEquals(200, response.getStatusLine().getStatusCode()); 
     HttpEntity entity = response.getEntity(); 

     System.out.println("----------------------------------------"); 
     System.out.println(response.getStatusLine()); 
     EntityUtils.consume(entity); 
    } 
} 
종속 버전

메이븐 POM : 나는 또한 간단한을 발표했습니다

<?xml version="1.0" encoding="UTF-8"?> 
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
    <modelVersion>4.0.0</modelVersion> 

    <groupId>com.acme</groupId> 
    <artifactId>httptests</artifactId> 
    <version>0.0.1-SNAPSHOT</version> 
    <properties> 
     <maven.compiler.source>1.8</maven.compiler.source> 
     <maven.compiler.target>1.8</maven.compiler.target> 
    </properties> 
    <dependencies> 
     <dependency> 
      <groupId>org.apache.httpcomponents</groupId> 
      <artifactId>httpclient</artifactId> 
      <version>4.5.3</version> 
     </dependency> 
     <dependency> 
      <groupId>junit</groupId> 
      <artifactId>junit</artifactId> 
      <version>4.12</version> 
      <scope>test</scope> 
     </dependency> 
    </dependencies> 
    <build> 
     <plugins> 
      <plugin> 
       <groupId>org.apache.maven.plugins</groupId> 
       <artifactId>maven-surefire-plugin</artifactId> 
       <version>2.9</version> 
       <!-- this is not needed, but useful if you want to debug what's going 
        on with your connection --> 
       <configuration> 
        <argLine>-Djavax.net.debug=all</argLine> 
       </configuration> 
      </plugin> 
     </plugins> 
    </build> 
</project> 

test page 클라이언트 인증서를 테스트합니다.


다음은 추가 라이브러리없이 표준 Java API를 사용하여 클라이언트 인증서를 사용하는 예입니다.

import org.junit.Test; 

import javax.net.ssl.HttpsURLConnection; 
import javax.net.ssl.KeyManager; 
import javax.net.ssl.KeyManagerFactory; 
import javax.net.ssl.SSLContext; 
import java.io.BufferedReader; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.net.URL; 
import java.security.KeyStore; 

public class PlainJavaHTTPS2Test { 

    @Test 
    public void testJKSKeyStore() throws Exception { 
     final String KEYSTOREPATH = "clientkeystore.jks"; 
     final char[] KEYSTOREPASS = "keystorepass".toCharArray(); 
     final char[] KEYPASS = "keypass".toCharArray(); 

     try (InputStream storeStream = this.getClass().getResourceAsStream(KEYSTOREPATH)) { 
      setSSLFactories(storeStream, "JKS", KEYSTOREPASS, KEYPASS); 
     } 
     testPlainJavaHTTPS(); 
    } 
    @Test 
    public void testP12KeyStore() throws Exception { 
     final String KEYSTOREPATH = "clientkeystore.p12"; 
     final char[] KEYSTOREPASS = "keystorepass".toCharArray(); 
     final char[] KEYPASS = "keypass".toCharArray(); 

     try (InputStream storeStream = this.getClass().getResourceAsStream(KEYSTOREPATH)) { 
      setSSLFactories(storeStream, "PKCS12", KEYSTOREPASS, KEYPASS); 
     } 
     testPlainJavaHTTPS(); 
    } 
    private static void setSSLFactories(InputStream keyStream, String keystoreType, char[] keyStorePassword, char[] keyPassword) throws Exception 
    { 
     KeyStore keyStore = KeyStore.getInstance(keystoreType); 

     keyStore.load(keyStream, keyStorePassword); 

     KeyManagerFactory keyFactory = 
       KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); 

     keyFactory.init(keyStore, keyPassword); 

     KeyManager[] keyManagers = keyFactory.getKeyManagers(); 

     SSLContext sslContext = SSLContext.getInstance("SSL"); 
     sslContext.init(keyManagers, null, null); 
     SSLContext.setDefault(sslContext); 
    } 

    public void testPlainJavaHTTPS() throws Exception { 
     String httpsURL = "https://slsh.iki.fi/client-certificate/protected/"; 
     URL myUrl = new URL(httpsURL); 
     HttpsURLConnection conn = (HttpsURLConnection)myUrl.openConnection(); 
     try (InputStream is = conn.getInputStream()) { 
      InputStreamReader isr = new InputStreamReader(is); 
      BufferedReader br = new BufferedReader(isr); 

      String inputLine; 

      while ((inputLine = br.readLine()) != null) { 
       System.out.println(inputLine); 
      } 
     } 
    } 
} 

그리고 여기에 코드의 최소한의와 세 번째 버전입니다,하지만) 키 스토어가없는 단지 내 디스크에있는 파일이라는 사실에 의존하는, 그리고 b)는 키 암호 스토어 동일해야합니다 암호. 상기 코드 세트

import org.junit.BeforeClass; 
import org.junit.Test; 

import java.net.URL; 
import java.io.*; 
import javax.net.ssl.HttpsURLConnection; 

public class PlainJavaHTTPSTest { 

    @BeforeClass 
    public static void setUp() { 
     System.setProperty("javax.net.ssl.keyStore", "/full/path/to/clientkeystore-samepassword.jks"); 
     System.setProperty("javax.net.ssl.keyStorePassword", "keystorepass"); 
    } 

    @Test 
    public void testPlainJavaHTTPS() throws Exception { 
     String httpsURL = "https://slsh.iki.fi/client-certificate/protected/"; 
     URL myUrl = new URL(httpsURL); 
     HttpsURLConnection conn = (HttpsURLConnection)myUrl.openConnection(); 
     try (InputStream is = conn.getInputStream()) { 
      InputStreamReader isr = new InputStreamReader(is); 
      BufferedReader br = new BufferedReader(isr); 

      String inputLine; 

      while ((inputLine = br.readLine()) != null) { 
       System.out.println(inputLine); 
      } 
     } 
    } 
} 

특성은 물론 또한 기동 파라미터 -Djavax.net.ssl.keyStore=/full/path/to/clientkeystore-samepassword.jks-Djavax.net.ssl.keyStorePassword=keystorepass과 같이 주어질 수있다.

11

Java HTTP 클라이언트 대신 Apache HTTP 클라이언트를 사용하려면 SSLFactory에 키 스토어를 제공하고 DefaultHTTPClient가 HTTPS 프로토콜에서이를 사용하도록 구성해야합니다.

작동 예제 here을 찾을 수 있습니다.

도움이 되었기를 바랍니다.

+0

Java HTTP 클라이언트를 사용하기위한 몇 가지 지침을 제공 할 수 있습니까? 나는 아파치 하나에 어려움을 겪고있다. – Ravi

+5

내가 잘못 생각한 것 같습니다.하지만이 예는 클라이언트를 인증하기위한 클라이언트 인증서를 제공하는 대신 사용자 정의 트러스트 스토어 (예 : 일반적으로 신뢰할 수없는 인증서를 신뢰하는 것)를 사용하는 것일뿐입니다. –

+0

이것은 질문에 대답하지 않습니다. 이렇게하면 클라이언트 인증서가 아닌 사용자 지정 트러스트 스토어 만 추가됩니다. – sstendal

관련 문제