2010-02-22 54 views
33

Tôi cần thiết lập một máy chủ HTTPS thực sự nhẹ cho một ứng dụng Java. Đó là một mô phỏng được sử dụng trong các phòng thí nghiệm phát triển của chúng tôi để mô phỏng các kết nối HTTPS được chấp nhận bởi một thiết bị trong tự nhiên. Bởi vì nó hoàn toàn là một công cụ phát triển nhẹ và không được sử dụng trong sản xuất theo bất kỳ cách nào cả, tôi khá vui khi bỏ qua các chứng nhận và nhiều thương lượng nhất có thể.Máy chủ HTTPS Java đơn giản

Tôi đang lập kế hoạch sử dụng lớp HttpsServer trong Java 6 SE nhưng tôi đang cố gắng để làm cho nó hoạt động. Là khách hàng thử nghiệm, tôi đang sử dụng wget từ dòng lệnh cygwin (wget https://[address]:[port]) nhưng wget báo cáo rằng "Không thể thiết lập kết nối SSL".

Nếu tôi chạy wget với tùy chọn -d để gỡ lỗi, nó cho tôi biết "Bắt tay SSL không thành công".

Tôi đã dành 30 phút googling này và tất cả mọi thứ dường như chỉ trở lại tài liệu Java6 khá vô dụng mô tả các phương pháp nhưng không thực sự nói về làm thế nào để có được những điều darn nói hoặc cung cấp bất kỳ mã ví dụ ở tất cả .

Có ai có thể đưa tôi đi đúng hướng không?

Trả lời

38

Những gì tôi cuối cùng được sử dụng là điều này:

try 
{ 
    // setup the socket address 
    InetSocketAddress address = new InetSocketAddress (InetAddress.getLocalHost(), config.getHttpsPort()); 

    // initialise the HTTPS server 
    HttpsServer httpsServer = HttpsServer.create (address, 0); 
    SSLContext sslContext = SSLContext.getInstance ("TLS"); 

    // initialise the keystore 
    char[] password = "simulator".toCharArray(); 
    KeyStore ks = KeyStore.getInstance ("JKS"); 
    FileInputStream fis = new FileInputStream ("lig.keystore"); 
    ks.load (fis, password); 

    // setup the key manager factory 
    KeyManagerFactory kmf = KeyManagerFactory.getInstance ("SunX509"); 
    kmf.init (ks, password); 

    // setup the trust manager factory 
    TrustManagerFactory tmf = TrustManagerFactory.getInstance ("SunX509"); 
    tmf.init (ks); 

    // setup the HTTPS context and parameters 
    sslContext.init (kmf.getKeyManagers(), tmf.getTrustManagers(), null); 
    httpsServer.setHttpsConfigurator (new HttpsConfigurator(sslContext) 
    { 
     public void configure (HttpsParameters params) 
     { 
      try 
      { 
       // initialise the SSL context 
       SSLContext c = SSLContext.getDefault(); 
       SSLEngine engine = c.createSSLEngine(); 
       params.setNeedClientAuth (false); 
       params.setCipherSuites (engine.getEnabledCipherSuites()); 
       params.setProtocols (engine.getEnabledProtocols()); 

       // get the default parameters 
       SSLParameters defaultSSLParameters = c.getDefaultSSLParameters(); 
       params.setSSLParameters (defaultSSLParameters); 
      } 
      catch (Exception ex) 
      { 
       ILogger log = new LoggerFactory().getLogger(); 
       log.exception (ex); 
       log.error ("Failed to create HTTPS port"); 
      } 
     } 
    }); 
    LigServer server = new LigServer (httpsServer); 
    joinableThreadList.add (server.getJoinableThread()); 
} 
catch (Exception exception) 
{ 
    log.exception (exception); 
    log.error ("Failed to create HTTPS server on port " + config.getHttpsPort() + " of localhost"); 
} 

Để tạo keystore:

$ keytool -genkey -alias alias -keypass simulator \ 
    -keystore lig.keystore -storepass simulator 

Xem thêm here.

Có khả năng lưu trữ và điểm vượt qua có thể khác nhau, trong trường hợp này, ks.loadkmf.init phải sử dụng kho lưu trữ và móc khóa tương ứng.

+1

Hi, lúc này bạn có chỉ định chứng chỉ và khóa riêng của mình không? chúng được tạo tự động? – Cemre

+0

Xin chào, vẫn là một người mới. chỉ cần tự hỏi nếu bạn đang sử dụng SSLContext mà bạn đã tạo khi thiết lập cấu hình? Vì bạn ghi đè phương thức cấu hình và gọi getDefault(). Không sử dụng SSLContext được truyền trong hàm tạo. – william

+0

HI, Cách thêm xác thực ứng dụng khách? – Hoysala

10

tôi cập nhật câu trả lời của bạn cho một máy chủ https (không ổ cắm based), Nó có thể giúp với CSRF và AJAX Gọi

import java.io.*; 
import java.net.InetSocketAddress; 
import java.lang.*; 
import java.net.URL; 
import com.sun.net.httpserver.HttpsServer; 
import java.security.KeyStore; 
import javax.net.ssl.KeyManagerFactory; 
import javax.net.ssl.TrustManagerFactory; 
import com.sun.net.httpserver.*; 
import javax.net.ssl.SSLEngine; 
import javax.net.ssl.SSLParameters; 

import java.io.InputStreamReader; 
import java.io.Reader; 
import java.net.URLConnection; 

import javax.net.ssl.HostnameVerifier; 
import javax.net.ssl.HttpsURLConnection; 
import javax.net.ssl.SSLContext; 
import javax.net.ssl.SSLSession; 
import javax.net.ssl.TrustManager; 
import javax.net.ssl.X509TrustManager; 
import java.security.cert.X509Certificate; 

import java.net.InetAddress; 
import com.sun.net.httpserver.HttpExchange; 
import com.sun.net.httpserver.HttpHandler; 
import com.sun.net.httpserver.HttpServer; 
import com.sun.net.httpserver.HttpsExchange; 

public class SimpleHTTPSServer { 

    public static class MyHandler implements HttpHandler { 
     @Override 
     public void handle(HttpExchange t) throws IOException { 
      String response = "This is the response"; 
      HttpsExchange httpsExchange = (HttpsExchange) t; 
      t.getResponseHeaders().add("Access-Control-Allow-Origin", "*"); 
      t.sendResponseHeaders(200, response.length()); 
      OutputStream os = t.getResponseBody(); 
      os.write(response.getBytes()); 
      os.close(); 
     } 
    } 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) throws Exception { 

     try { 
      // setup the socket address 
      InetSocketAddress address = new InetSocketAddress(8000); 

      // initialise the HTTPS server 
      HttpsServer httpsServer = HttpsServer.create(address, 0); 
      SSLContext sslContext = SSLContext.getInstance("TLS"); 

      // initialise the keystore 
      char[] password = "password".toCharArray(); 
      KeyStore ks = KeyStore.getInstance("JKS"); 
      FileInputStream fis = new FileInputStream("testkey.jks"); 
      ks.load(fis, password); 

      // setup the key manager factory 
      KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); 
      kmf.init(ks, password); 

      // setup the trust manager factory 
      TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); 
      tmf.init(ks); 

      // setup the HTTPS context and parameters 
      sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 
      httpsServer.setHttpsConfigurator(new HttpsConfigurator(sslContext) { 
       public void configure(HttpsParameters params) { 
        try { 
         // initialise the SSL context 
         SSLContext c = SSLContext.getDefault(); 
         SSLEngine engine = c.createSSLEngine(); 
         params.setNeedClientAuth(false); 
         params.setCipherSuites(engine.getEnabledCipherSuites()); 
         params.setProtocols(engine.getEnabledProtocols()); 

         // get the default parameters 
         SSLParameters defaultSSLParameters = c.getDefaultSSLParameters(); 
         params.setSSLParameters(defaultSSLParameters); 

        } catch (Exception ex) { 
         System.out.println("Failed to create HTTPS port"); 
        } 
       } 
      }); 
      httpsServer.createContext("/test", new MyHandler()); 
      httpsServer.setExecutor(null); // creates a default executor 
      httpsServer.start(); 

     } catch (Exception exception) { 
      System.out.println("Failed to create HTTPS server on port " + 8000 + " of localhost"); 
      exception.printStackTrace(); 

     } 
    } 

} 

Để tạo một chứng chỉ tự ký

keytool -genkey -keyalg RSA -alias selfsigned -keystore testkey.jks -storepass password -validity 360 -keysize 2048 
+2

'setExecutor (null)' tạo một máy chủ đơn luồng. Để có một máy chủ đa luồng, bạn cần cung cấp một trình thực thi thích hợp. Ví dụ: 'httpsServer.setExecutor (new ThreadPoolExecutor (4, 8, 30, TimeUnit.SECONDS, new ArrayBlockingQueue (100))); ' – rustyx

+0

Xin chào, vẫn là một newbie. chỉ cần tự hỏi nếu bạn đang sử dụng SSLContext mà bạn đã tạo khi thiết lập cấu hình? Vì bạn ghi đè phương thức cấu hình và gọi getDefault(). Không sử dụng SSLContext được truyền trong hàm tạo. – william

+0

Nói đúng, bạn nên gọi 't.sendResponseHeaders' với' response.getBytes(). Length' thay vì 'response.length()'. Nó làm việc với chuỗi trong ví dụ của bạn, nhưng sẽ phá vỡ cho '" Hëllö Wörld "'. – Torgny

Các vấn đề liên quan