Avatar billede kkaen Nybegynder
24. maj 2010 - 20:48 Der er 27 kommentarer og
1 løsning

Sende data til en SSL-form

Jeg forsøger at oprette en javafil, som åbner en forbindelse til en form med ssl.

Forsøgskoden er hentet her:
http://www.devx.com/Java/Article/17679/1954
http://www.java2s.com/Tutorial/Java/0490__Security/SSLClientwithjavaxnetssltrustStoresetting.htm
http://www.exampledepot.com/egs/javax.net.ssl/client.html

Jeg har hentet certifikatet fra pågældende form, konverteret den, og tilføjet den til mit Eclipse-system.

Løsningerne giver forskellige fejl. Den sidste implementering giver: "password tampered with".
Den føste og oprindelige løsning giver: "the trustAnchors parameter must be non-empty".

Kender nogle en løsning på problemet?

Jeg har forsøgt de følgende 3 måder:

String filename = System.getProperty("java.home")
            + "/lib/security/cacerts".replace('/', File.separatorChar);
System.out.println("Filename= "+filename);            System.setProperty("javax.net.ssl.trustStore",filename);
System.setProperty("javax.net.ssl.trustStorePassword","kode");
         
System.out.println("Url= "+loginUrl+"?name="+loginName+"&password="+loginPassword);
String newUrl= loginUrl+"?name="+loginName+"&password="+loginPassword;
                        System.setProperty("javax.net.ssl.trustStore", newUrl);           
//Create streams to securely send and receive data to the server InputStream
InputStream is = new
URL(loginUrl+"?"+ServersLoginName+"="+loginName+"&"+ServersLoginPassword+"="+loginPassword).openStream();
URL(loginUrl+"?"+ServersLoginName+"="+loginName+"&"+ServersLoginPassword+"="+loginPassword).openConnection();

System.out.println("Attempt2:");
int port = 8080;
String hostname = loginUrl;
SocketFactory socketFactory = SSLSocketFactory.getDefault();
Socket socket = socketFactory.createSocket(hostname, port);
// Create streams to securely send and receive data to the server
InputStream in = socket.getInputStream();
OutputStream out2 = socket.getOutputStream();
// Read from in and write to out...
// Close the socket
in.close();
out2.close();
         
System.out.println("Attempt3:");         
SSLSocketFactory ssf = (SSLSocketFactory) SSLSocketFactory.getDefault();
Socket s = ssf.createSocket(loginUrl, 8080);
BufferedReader in2 = new BufferedReader(new InputStreamReader(s.getInputStream()));
String x = in2.readLine();
System.out.println(x);
in2.close();

Jeg har også forsøgt at følge disse vejledninger:
http://www.innovation.ch/java/HTTPClient/emulating_forms.html
http://java.sun.com/docs/books/tutorial/networking/urls/readingWriting.html
http://www.informit.com/guides/content.aspx?g=java&seqNum=44
http://www.theserverside.com/news/1365153/HttpClient-and-FileUpload
Men Eclipse brokker sig hele tiden over f.eks. "unable to find valid certification path to requested target", "password tampered with" eller andet.
Avatar billede arne_v Ekspert
25. maj 2010 - 03:47 #1
Har du behov for at sende et client certfikat eller behov for at lave et meget grundigt check af server certifikat?

Eller vil du bare bruge HTTPS for at få forbindelsen krypteret?
Avatar billede arne_v Ekspert
25. maj 2010 - 03:50 #2
Det sidste er rimeligt nemt.

:-)

Eksempel på GET:


import java.net.*;
import java.io.*;
import java.security.*;
import java.security.cert.*;

import javax.net.ssl.*;

public class HttpsGet {
  public static void main(String[] args) {
      try {
        SSLContext sslctx = SSLContext.getInstance("SSL");
        sslctx.init(null, new X509TrustManager[] { new MyTrustManager() }, null);
        HttpsURLConnection.setDefaultSSLSocketFactory(sslctx.getSocketFactory());
        //HttpsURLConnection.setDefaultHostnameVerifier(new MyHostnameVerifier());
        URL url = new URL("https://www.xxxx.dk/");
        HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
        if (con.getResponseCode() == HttpsURLConnection.HTTP_OK) {
            InputStream is = con.getInputStream();
            OutputStream os = new FileOutputStream("C:\\z.z");
            byte[] b = new byte[1000];
            int n;
            while ((n = is.read(b)) >= 0) {
              os.write(b, 0, n);
            }
            os.close();
            is.close();
        }
        con.disconnect();
      } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
      } catch (KeyManagementException e) {
        e.printStackTrace();
      } catch (MalformedURLException e) {
        e.printStackTrace();
      } catch (FileNotFoundException e) {
        e.printStackTrace();
      } catch (IOException e) {
        e.printStackTrace();
      }
  }
}
class MyTrustManager implements X509TrustManager
{
    public void checkClientTrusted(X509Certificate[] chain, String authType) {
    }
    public void checkServerTrusted(X509Certificate[] chain, String authType) {
    }
    public X509Certificate[] getAcceptedIssuers() {
        return null;
    }
}

//class MyHostnameVerifier implements HostnameVerifier {
//  public boolean verify(String urlHostName, SSLSession session) {
//      return true;
//  }
//}



Eksempel på POST:


import java.io.*;
import java.net.*;
import java.security.cert.*;

import javax.net.ssl.*;

public class HttpsPost {
    public static void main(String[] args) throws Exception {
        SSLContext sslctx = SSLContext.getInstance("SSL");
        sslctx.init(null, new X509TrustManager[] { new MyTrustManager() }, null);
        HttpsURLConnection.setDefaultSSLSocketFactory(sslctx.getSocketFactory());
        URL url = new URL("https://www.xxxx.dk/htbin/tell2");
        HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
        con.setRequestMethod("POST");
        con.setDoOutput(true);
        PrintStream ps = new PrintStream(con.getOutputStream());
        ps.println("f1=abc&f2=xyz");
        ps.close();
        con.connect();
        if (con.getResponseCode() == HttpsURLConnection.HTTP_OK) {
            BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
            String line;
            while((line = br.readLine()) != null) {
                System.out.println(line);
            }
            br.close();
        }
        con.disconnect();
    }
}

class MyTrustManager implements X509TrustManager {
    public void checkClientTrusted(X509Certificate[] chain, String authType) {
    }
    public void checkServerTrusted(X509Certificate[] chain, String authType) {
    }
    public X509Certificate[] getAcceptedIssuers() {
        return new X509Certificate[0];
    }
}


Hvis det første så kræver det noget mere.

:-(
Avatar billede kkaen Nybegynder
25. maj 2010 - 08:43 #3
"Har du behov for at sende et client certfikat eller behov for at lave et meget grundigt check af server certifikat?

Eller vil du bare bruge HTTPS for at få forbindelsen krypteret?"

Hmm, at sende et klient-certifikat, vil det sige, at klienten sender et certifikat på sig selv?
Et meget grundigt check af server-certifikat lyder lidt overkill. Men der skal være et check deraf (går jeg ud fra), eftersom klienten ellers ikke har mulighed for at sende form-data til serveren (derfor fejlene: "unable to find valid certification path to requested target" og "password tampered with").

I al sin simpelhed så vil jeg blot gerne sende data til en server, som normalt skal have det indtastet i form-felter. Jeg gik ud fra, at man blot kunne benytte jsp's mulighed for at sende argumenter med i url'en f.eks.. Men da der er problemer med et certifikat på serversiden, så har jeg opbragt en kopi deraf, så jeg kan sætte den ind på klientsiden rent programmerings-mæssigt (hvis der er behov for dette?). Men de videre skridt i processen er jeg i tvivl om. Specielt når Eclipse brokker sig uanset hvilke løsningsforslag jeg forsøger.
Avatar billede kkaen Nybegynder
25. maj 2010 - 17:57 #4
Jeg gik egentlig ud fra, at det var rimeligt simpelt, hvis/når man mestrer anvendelse af sikkerheds-mekanismen. Det er vel den, der klages over i nogle af de fejlmeddelelser, jeg får.

Jeg går også ud fra, at X509TrustManager[] netop er en foranstaltning til at tage kontrol over den sikkerhedsmekanisme. Men hvordan får man den til at virke sammen med sig egen *.crt/*.cer/*.p7c/*.der ? Det kan man da, hvis man laver sin egen applikation helt fra bundet af - så vidt jeg ved af ?
Avatar billede arne_v Ekspert
25. maj 2010 - 20:41 #5
Et client certifikat kan bruges til at authentificate brugeren, saa skal der ikke indtastes brugernavn & password, fordi serveren kan se paa certifikat hvem nan er.
Avatar billede arne_v Ekspert
25. maj 2010 - 20:43 #6
Hvis du bare vil emulere hvad en (aeldre browser uden anti-phising funktionalitet) browser goer med HTTPS URL'er saa er det ret simpelt og jeg har postet koden. Og du skal slet ikke lave nogfet certifikater.
Avatar billede kkaen Nybegynder
25. maj 2010 - 21:03 #7
Nu er det jo meningen, at jeg gennem java-kode kan sende form-data til en server. Og serveren har et certifikat. Så jeg er ikke sikker på, at den kode gør tricket.
Avatar billede arne_v Ekspert
25. maj 2010 - 21:39 #8
POST eksemplet sender form data.
Avatar billede kkaen Nybegynder
25. maj 2010 - 21:44 #9
Okay - jeg prøver lige at teste en implementering af den i nærmeste fremtid.

Nu har jeg lige set lidt på koden, skal man egentlig ikke også kalde en submit-funktion (f.eks. gennem "ps.println()", eller gøres dette automatisk gennem metode-valgene?
Avatar billede arne_v Ekspert
25. maj 2010 - 22:07 #10
Submit er implicit ved HTTP requesten.

Nogen gange sendes navn paa submit button med i form data, men det er sjaeldent noedvendigt.
Avatar billede kkaen Nybegynder
25. maj 2010 - 22:32 #11
Okay - det må kræve en test :-)
Avatar billede kkaen Nybegynder
29. maj 2010 - 20:36 #12
Nu har jeg forsøgt, at implementere dit forslag.
Ved første kørsel printes html-koden ud for login-siden. Dette var vel ikke meningen? Skulle det ikke være html-koden for siden, der kommer frem, EFTER man er logget ind?

Jeg forsøgte så at lave en kopi af første login-kørsel inde i

if (con.getResponseCode() == HttpsURLConnection.HTTP_OK) {

så man kunne aktivere knapper inde på siden, efter man var logget ind. Men igen bliver den oprindelige html-kode blot udskrevet ved

if (con.getResponseCode() == HttpsURLConnection.HTTP_OK) {

Jeg har naturligvis ændret loginnavn og loginkode samt url'er, men det eneste, der sker, er som sagt, at html-koden for første login-side bliver udskrevet.

Kan det være fordi, der ikke er sat en korrekt TrustManager op? Eller kan det være fordi, de rigtige id-felter ikke bliver udfyld, hvorefter en submit bliver gennemført (jeg har angivet felternes id'er inde i ps.println()-strengen)?

Ellers er metoden "POST" og der køres en javascript-funktion ved onSubmit.
Avatar billede kkaen Nybegynder
29. maj 2010 - 20:40 #13
Jeg har forresten fundet dette eksempel på implementering af ssl og keymanager.

http://www.java2s.com/Tutorial/Java/0490__Security/SSLContextandKeymanager.htm

Mon det har noget at sige i denne forbindelse til opsætningen, eller er dit oprindelige eksempel tilstrækkeligt?
Avatar billede arne_v Ekspert
01. juni 2010 - 04:06 #14
Jeg forstår ikke det med HTML fra før og efter login.

Når en browser logger ind så sker det som:
- browser laver GET på login side
- browser laver POST med login info

Det er to forskellige requests.

Som naturligvis returnerer forskelligt HTML.

Når du logger ind med et program så kan du formentligt spring den første request over og submitte direkte.

(pas på med ASP.NET web forms - de er vanskeligere !)

Så en POST med login info og så bør du få output efter login.
Avatar billede arne_v Ekspert
01. juni 2010 - 04:07 #15
Linket er igen noget med egen keystore.
Avatar billede kkaen Nybegynder
01. juni 2010 - 08:40 #16
HTML før og efter login er såmæn blot, at der typisk er et login-område på siden (hvilket også fremgår af html'en), som efter loginet er ændret, eller der måske er redirected til en helt anden side (hvilket også fremgår af html'en).

"(pas på med ASP.NET web forms - de er vanskeligere !)"
-> okay. Jeg troede ellers, at asp.net's loginform hurtigt ville kunne klare det. Men nu er det jo java, så det kan vi se bort fra.

"Så en POST med login info og så bør du få output efter login."
-> ja, det var også dette, jeg antog. Men da jeg prøvede POST-eksemplet med felt-name og felt-values i url'en, og programmet så efterfølgende læste og udskrev den returnerede html, så kom den oprindelige html ud. Altså så login-området stadig var der - ligesom hvis man ikke have logget ind. Derfor min forvirring.
Avatar billede kkaen Nybegynder
01. juni 2010 - 09:35 #17
"Linket er igen noget med egen keystore."
-> så det skal altså ikke betragtes som "egen" keystore, selvom man poster til en form med indbygget security? Det var blot den tanke, jeg havde, eftersom en browser skal acceptere en policy-file. Så skal form-submitteren i java vel også implementere noget lignende. Og der troede jeg, at det var at betragte som en "egen" keystore...
Avatar billede arne_v Ekspert
02. juni 2010 - 04:29 #18
ASP.NET win forms har ikke-konstant viewstate i et hidden felt der skal submittes sammen med username/password. Masser af problemer.
Avatar billede arne_v Ekspert
02. juni 2010 - 04:31 #19
Du skal bruge en keystore hvis X509TrustManager skal checke certfikatet.

Men mit forslag vil være at få det basale HTTPS POST til at virke uden check og så kigge på check bagefter.
Avatar billede arne_v Ekspert
02. juni 2010 - 04:31 #20
Jeg bliver nok nødt til at prøve at lave et eksempel.
Avatar billede kkaen Nybegynder
02. juni 2010 - 08:27 #21
"Men mit forslag vil være at få det basale HTTPS POST til at virke uden check og så kigge på check bagefter."
-> det stiler jeg også efter. Små skridt ad gangen. Jeg er blot ikke klar over, om man kan teste for opnået forbindelse i den sammenhæng så. Men det burde man vel, for man vil vel altid få en form for responce.

"Jeg bliver nok nødt til at prøve at lave et eksempel."
-> det lyder rigtig godt :-)
Avatar billede kkaen Nybegynder
14. juni 2010 - 21:48 #22
Du skulle vel ikke være kommet videre med et eksempel? :-)
Avatar billede arne_v Ekspert
15. juni 2010 - 01:09 #23
Det er et af de spoergsmaal som kraever en del arbejde.

Saa indtil videre er jeg gaaet uden om det til fordel for lidt simplere spoergsmaal.
Avatar billede kkaen Nybegynder
15. juni 2010 - 08:10 #24
Det havde jeg også lidt på fornemmelsen ;-)
Avatar billede kkaen Nybegynder
15. juni 2010 - 18:00 #25
Efter lidt søgen ser det ud til, at der vist er en del flere personer, som har problemer med dette emne.

Nu har jeg fulgt vejledningen på:
http://alien.dowling.edu/~vassil/tutorials/javapost.php

Så har jeg ændret "HttpURLConnection" til "HttpsURLConnection", fulgt vejledningen til certifikat på:

http://www.java-samples.com/showtutorial.php?tutorialid=210

Og tilføjet denne kode til applikationen:

System.setProperty("javax.net.ssl.trustStore", "cacerts");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");

Men jeg får stadig exception:
Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty

Muligvis er det fordi, jeg ikke er 100% sikker på, hvilket cacerts-fil, jeg arbejder på, og derfor ikke kan referere til den...?
Avatar billede kkaen Nybegynder
27. juni 2010 - 20:29 #26
Nu har jeg forsøgt, at implementere brugen af cer-filen gennem gennemgangen her:
http://www.ehow.com/how_6562862_use-certificate-factory-java.html

Men under kørsel af koden bliver outputtet det samme. Jeg tror ikke rigtig, at jeg får aktiveret de rigtige felter og/eller knapper inde på den aktuelle netside, som skal modtage dataene. Hvordan er man helt sikker på, at man har fat i de rigtige elementer, og aktiverer dem?
Avatar billede kkaen Nybegynder
30. december 2010 - 15:55 #27
Arne_v ->
Lægger du lige et "svar" ?
Avatar billede arne_v Ekspert
30. december 2010 - 17:52 #28
yes
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester



IT-JOB

Politiets Efterretningstjeneste

Testere med flair for test management

Cognizant Technology Solutions Denmark ApS

Senior Test Manager

Cognizant Technology Solutions Denmark ApS

Service Line Specialist - ServiceNow (Thirdera)