# HTTPs Server



## agent47 (29. Jan 2016)

Hallo, 

für mein Projekt benötige ich einen SSL Gesicherten Webserver. Nach etwas suchen habe ich gefunden das Java schon einen Einfachen solchen Server mitbringt. Nun habe ich versucht zum Test einen solchen Server zu starten, leider klappt das nicht.
Vorgegangen bin ich nach folgendem Tutotrial: 
http://www.codeproject.com/Tips/1043003/Create-a-Simple-Web-Server-in-Java-HTTPS-Server


```
import com.sun.net.httpserver.*;

import javax.net.ssl.*;
import java.io.*;
import java.net.InetSocketAddress;
import java.net.URI;
import java.net.URLDecoder;
import java.security.*;
import java.security.cert.CertificateException;
import java.time.LocalDateTime;
import java.util.*;

/**
* Tutorial von http://www.codeproject.com/Tips/1040097/Create-a-Simple-Web-Server-in-Java-HTTP-Server
* und http://www.codeproject.com/Tips/1043003/Create-a-Simple-Web-Server-in-Java-HTTPS-Server
*/
public class TsteHttpServer {

    public class RootHandler implements HttpHandler {

        @Override
        public void handle(HttpExchange he) throws IOException {

            StringBuffer response = new StringBuffer();
            response.append("<html><head><title>Datum</title></head><body><h1>");
            response.append(LocalDateTime.now());
            response.append("</h1></body></html>");

            he.sendResponseHeaders(200, response.length());
            OutputStream os = he.getResponseBody();
            os.write(response.toString().getBytes());
            os.close();
        }
    }

    public class EchoHeaderHandler implements HttpHandler {

        @Override
        public void handle(HttpExchange he) throws IOException {
            Headers headers = he.getRequestHeaders();
            Set<Map.Entry<String, List<String>>> entries = headers.entrySet();
            String response = "";
            for (Map.Entry<String, List<String>> entry : entries)
                response += entry.toString() + "\n";
            he.sendResponseHeaders(200, response.length());
            OutputStream os = he.getResponseBody();
            os.write(response.toString().getBytes());
            os.close();
        }
    }

    public class EchoGetHandler implements HttpHandler {

        @Override

        public void handle(HttpExchange he) throws IOException {
            // parse request
            Map<String, Object> parameters = new HashMap<>();
            URI requestedUri = he.getRequestURI();
            String query = requestedUri.getRawQuery();
            parseQuery(query, parameters);

            // send response
            String response = "";
            for (String key : parameters.keySet())
                response += key + " = " + parameters.get(key) + "\n";
            he.sendResponseHeaders(200, response.length());
            OutputStream os = he.getResponseBody();
            os.write(response.toString().getBytes());

            os.close();
        }
    }

    public class EchoPostHandler implements HttpHandler {

        @Override

        public void handle(HttpExchange he) throws IOException {

            // parse request
            Map<String, Object> parameters = new HashMap<String, Object>();
            InputStreamReader isr = new InputStreamReader(he.getRequestBody(), "utf-8");
            BufferedReader br = new BufferedReader(isr);
            String query = br.readLine();
            parseQuery(query, parameters);

            // send response
            String response = "";
            for (String key : parameters.keySet())
                response += key + " = " + parameters.get(key) + "\n";
            he.sendResponseHeaders(200, response.length());
            OutputStream os = he.getResponseBody();
            os.write(response.toString().getBytes());
            os.close();
        }
    }

    public TsteHttpServer() throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyManagementException {

        String keystoreFilename = "mykey.keystore";
        char[] storepass = "mypassword".toCharArray();
        char[] keypass = "mypassword".toCharArray();
        String alias = "alias";

        // load certificate
        FileInputStream fIn = new FileInputStream(keystoreFilename);
        KeyStore keystore = KeyStore.getInstance("JKS");
        keystore.load(fIn, storepass);

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

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

        // create ssl context
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

        // create https server
        int port = 9000;
        HttpsServer server = HttpsServer.create(new InetSocketAddress(port), 0);

        // setup the HTTPS context and parameters
        server.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) {

                    ex.printStackTrace();
                    System.out.println("Failed to create HTTPS server");
                }
            }
        });

        //HttpServer server = HttpServer.create(new InetSocketAddress(port), 0);
        System.out.println("server started at " + port);
        server.createContext("/", new RootHandler());
        server.createContext("/echoHeader", new EchoHeaderHandler());
        server.createContext("/echoGet", new EchoGetHandler());
        server.createContext("/echoPost", new EchoPostHandler());
        server.setExecutor(null);
        server.start();
    }

    public static void main(String[] args) throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyManagementException {

        new TsteHttpServer();
    }

    public static void parseQuery(String query, Map<String,
            Object> parameters) throws UnsupportedEncodingException {

        if (query != null) {
            String pairs[] = query.split("[&]");
            for (String pair : pairs) {
                String param[] = pair.split("[=]");
                String key = null;
                String value = null;
                if (param.length > 0) {
                    key = URLDecoder.decode(param[0],
                            System.getProperty("file.encoding"));
                }

                if (param.length > 1) {
                    value = URLDecoder.decode(param[1],
                            System.getProperty("file.encoding"));
                }

                if (parameters.containsKey(key)) {
                    Object obj = parameters.get(key);
                    if (obj instanceof List<?>) {
                        List<String> values = (List<String>) obj;
                        values.add(value);

                    } else if (obj instanceof String) {
                        List<String> values = new ArrayList<>();
                        values.add((String) obj);
                        values.add(value);
                        parameters.put(key, values);
                    }
                } else {
                    parameters.put(key, value);
                }
            }
        }
    }
}
```

Der Server lässt dich ohne Fehlermeldung starten. Der Browser sagt mit dann aber "Fehler: Gesicherte Verbindung fehlgeschlagen". 
Kann mir vielleicht jemand einen Tipp geben was da falsch läuft?


----------



## Thallius (29. Jan 2016)

Ohne das ich mich mit Java-Web-Servern ausekenne, gehe mal davon aus, dass der Browser nur das fehlende Zertifikat bemängelt oder? Weil Du kannst zwar einen https Server einrichten, solange der aber kein gültiges Zertifikat hat (Muss man kaufen), wird kein Browser auf der Welt diesen als sichere Verbindung erkennen.

Du kannst aber normalerweise dem Browser sagen, dass Du dem Server trotzdem vertraust indem Du ein eigenes Zertifikat erstellst (kostet kein Geld) und dieses dann als vertrauenswürdig bei deinem Browser einstellst. Das geht dann aber natürlich nur mit diesem einen Browser. 

Weiterhin kannst du bei jedem Browser trotzdem die Verbindung aufbauen und es ist dann tatsächlich auch eine verschlüsselte https Verbindung aber eben keine gesicherte.

Gruß

Claus


----------



## agent47 (29. Jan 2016)

Genau die Option bieter mir kein Browser an (Firefox, Chrome, Opera), das Zertifikat trotzdem zu akzeptieren. 
Eigentlich wollte ich dafür auch nanohttpd nehmen, aber dafür habe ich nichts gefunden wie man das Verschlüsseln kann. Möglich ist das aber laut Beschreibung auf GitHub -> https://github.com/NanoHttpd/nanohttpd#core


----------



## Bitfehler (29. Jan 2016)

Thallius hat gesagt.:


> Weil Du kannst zwar einen https Server einrichten, solange der aber kein gültiges Zertifikat hat (Muss man kaufen), wird kein Browser auf der Welt diesen als sichere Verbindung erkennen.



Nur mal so nebenbei. Es gibt seit kurzer Zeit die Initiative Let's Encrypt, bei der man kostenlos Zertifikate bekommen kann, die von den gängigen Browser auch akzeptiert werden. Der Haken dabei ist, dass diese immer nur drei Monate gültig sind und man sie dann verlängern lassen muss. Richtet man dafür einen cronjob ein, ist das aber auch kein unlösbares Problem.

Offizielle Seite: https://letsencrypt.org/

Kannst du nicht die angebotenen Verschlüsselungsmöglichkeiten von bekannten App-servern wie zum Beispiel Tomcat oder Glassfish nutzen?


----------



## agent47 (29. Jan 2016)

Das soll eine embedded App werden die auch nur eine kleine HTTP Schnittstelle haben wird. 

Wenn das Zertifikat nicht akzeptiert wird müsste der mir da nicht anbieten die Seite trotzdem zu öffnen?


----------



## Thallius (29. Jan 2016)

agent47 hat gesagt.:


> Das soll eine embedded App werden die auch nur eine kleine HTTP Schnittstelle haben wird.
> 
> Wenn das Zertifikat nicht akzeptiert wird müsste der mir da nicht anbieten die Seite trotzdem zu öffnen?



Also bei Chrome ist das Feature ziemlich versteckt. Da gibt es dann unten auf der Seite einen kleinen link "erweitert" und wenn man da drauf klickt kann man die Seite trotzdem aufmachen.

Gruß

Claus


----------

