[Java] Android Soap POST met Authenticatie

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Tripwire999
  • Registratie: Januari 2004
  • Laatst online: 10-10 20:19
Ik ben bezig met een iOS app te porten naar Android. Nu is dit een van de weinige keren dat ik bezig ben met Android, en heb ik dus nog niet veel ervaring met het opzetten van een connectie naar een webserivce.
Mijn iOS code is als volgt:

Objective-C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
NSString *soapMsg = [NSString stringWithFormat:
                     @"<soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:ns=\"http://www.schneider-electric.com/common/dataexchange/2011/05\">"
                        @"<soap:Header/>"
                        @"<soap:Body>"
                            @"<ns:GetValuesRequest>"
                                @"<ns:GetValuesIds>"
                                    @"<ns:Id>%@</ns:Id>"
                                @"</ns:GetValuesIds>"
                            @"</ns:GetValuesRequest>"
                        @"</soap:Body>"
                     @"</soap:Envelope>",
                     ewsId];

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:KUrl]];
[request addValue: @"application/soap+xml; charset=utf8"  forHTTPHeaderField:@"Content-Type"];
[request addValue:[NSString stringWithFormat:@"%@", KUrl] forHTTPHeaderField:@"SOAPAction"];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:[soapMsg dataUsingEncoding:NSUTF8StringEncoding]];

NSURLCredential *credential = [NSURLCredential credentialWithUser:KTestUsername password:kTestPassword persistence:NSURLCredentialPersistenceForSession];

AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation.securityPolicy setAllowInvalidCertificates:YES];
[operation.securityPolicy setValidatesDomainName:NO];
[operation setCredential:credential];


De bovenstaande code maakt gebruik van AFNetworking plugin en werkt perfect op iOS. Nu probeer ik dezelfde POST te doen op Android, maar ik krijg de authenticatie niet werkend. Ik maak gebruik van KSoap2, maar als er andere of betere suggesties zijn dan hoor ik het graag.
Mijn huidige code wat niet werkt:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
    String METHOD_NAME = "GetValues";
    String SOAP_ACTION = constants.getSOAP_URL() + METHOD_NAME;
    SoapObject request = new SoapObject(constants.getNAMESPACE(), METHOD_NAME);

    request.addProperty("Id", ewsId);

    //Setup authorization
    Element usernameElement = new Element().createElement(constants.getNAMESPACE(), "Username");
    usernameElement.addChild(Node.TEXT, constants.getSOAPUSERNAME());
    Element passwordElement = new Element().createElement(constants.getNAMESPACE(), "Password");
    passwordElement.addChild(Node.TEXT, constants.getSOAPPASSWORD());
    Element header = new Element().createElement(constants.getNAMESPACE(), "AuthHeader");
    header.addChild(Node.ELEMENT, usernameElement);
    header.addChild(Node.ELEMENT, passwordElement);

    SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER12);
    //envelope.dotNet = true;
    envelope.setOutputSoapObject(request);
    envelope.headerOut = new Element[]{header};

    //Also tried this didn't work :(
    /*
    List<HeaderProperty> headerList = new ArrayList<HeaderProperty>();
    String auth = constants.getSOAPUSERNAME() + ":" + constants.getSOAPPASSWORD();
    headerList.add(new HeaderProperty("Authorization", Base64.encode(auth.getBytes())));
    */

    HttpTransportSE transport = new HttpTransportSE(constants.getSOAP_URL());
    transport.debug = true;

    try
    {
        //transport.call(SOAP_ACTION, envelope, headerList);
        transport.call(SOAP_ACTION, envelope);
        Log.d("XML", transport.requestDump);
        Log.d("XML", transport.responseDump);
        return "Soap successfull!";
    }
    catch(Exception e)
    {
        Log.d("ERROR", "Error during soap action: " + e.toString());
        return "Error!";
    }


Als ik deze code run in de simulator of op mijn Android device krijg ik de melding in de debugger:
org.ksoap2.transport.HttpResponseException: HTTP request failed, HTTP status: 401

Er zit dus ergens iets niet goed met de autheticatie lijkt me. Iemand enig idee hoe ik dit het beste kan oplossen? Ik hoef in principe niet KSoap2 te gebruiken, dus als er andere plugins zijn die beter werken of makkelijker zijn hoor ik het graag!

Acties:
  • 0 Henk 'm!

Verwijderd

Kijk goed naar de berichten die je moet versturen en welke je daadwerkelijk verstuurd. Ik zie dat je het 1 en ander dumpt. Kijk op de ios client wat je moet versturen en probeer dat uit je android code te krijgen. Het kan zijn dat je een simpele import mist.

Ik zie deze namespace "http://www.schneider-electric.com/common/dataexchange/2011/05" namelijk niet in je android code terugkomen.

Acties:
  • 0 Henk 'm!

  • Tripwire999
  • Registratie: Januari 2004
  • Laatst online: 10-10 20:19
Verwijderd schreef op maandag 26 oktober 2015 @ 16:50:
Kijk goed naar de berichten die je moet versturen en welke je daadwerkelijk verstuurd. Ik zie dat je het 1 en ander dumpt. Kijk op de ios client wat je moet versturen en probeer dat uit je android code te krijgen. Het kan zijn dat je een simpele import mist.

Ik zie deze namespace "http://www.schneider-electric.com/common/dataexchange/2011/05" namelijk niet in je android code terugkomen.
Bedankt voor je reactie, ik heb inmiddels meerdere andere plugins geprobeerd maar ik krijg er geen werkend. Misschien mis ik inderdaad de namespace. Ga ik checken thx!

EDIT:
Ik had eigenlijk gehoopt gewoon dezelfde message te versturen op Android als op iOS (dus de geformatte string) maar schijnbaar is dat niet mogelijk op Android (geen een voorbeeld van gezien).

[ Voor 12% gewijzigd door Tripwire999 op 28-10-2015 20:44 ]


Acties:
  • 0 Henk 'm!

  • kluyze
  • Registratie: Augustus 2004
  • Niet online
Ik zie dat jij je username wachtwoord in de header van je soap envelope plaatst, terwijl origineel worden de credentials op het connection object geplaatst.

Ik weet niet of het handig is bij android apps, maar wij gebruiken eigenlijk altijd cxf voor soap connecties.

Acties:
  • 0 Henk 'm!

  • Tripwire999
  • Registratie: Januari 2004
  • Laatst online: 10-10 20:19
kluyze schreef op woensdag 28 oktober 2015 @ 20:54:
Ik zie dat jij je username wachtwoord in de header van je soap envelope plaatst, terwijl origineel worden de credentials op het connection object geplaatst.

Ik weet niet of het handig is bij android apps, maar wij gebruiken eigenlijk altijd cxf voor soap connecties.
Daar heb je inderdaad gelijk in, alleen geen idee hoe je dat bij kSoap2 doet. IK zal eens even onderzoeken.

Acties:
  • 0 Henk 'm!

  • Tripwire999
  • Registratie: Januari 2004
  • Laatst online: 10-10 20:19
Ik heb inmiddels verschillende dingen geprobeerd:
WSDL classes laten genereren -> werkt niet
Andere libs geprobeerd -> werkt niet

Ik krijg het ook niet voor elkaar om op het connection object in KSoap2 credentials te zetten. Iemand nog een idee, anders denk ik dat ik het moet opgeven...

EDIT:
Ben inmiddels wel een stukje verder gekomen:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
public class GetValues extends AsyncTask<String, String, String>
{
    private String ewsId;
    private Constants constants;

    public GetValues()
    {
        constants = new Constants();
    }

    protected String doInBackground(String[] params)
    {
        String METHOD_NAME = "GetValuesIn";
        String SOAP_ACTION = constants.getSOAP_URL() + "/" + METHOD_NAME;

        SoapObject request = new SoapObject(constants.getNAMESPACE(), METHOD_NAME);
        request.addProperty("ns:Id", ewsId);

        SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER12);
        envelope.dotNet = true;
        //envelope.implicitTypes = true;
        envelope.setOutputSoapObject(request);

        NtlmTransport transport = new NtlmTransport(constants.getSOAP_URL(), 10);
        transport.setCredentials(constants.getSOAPUSERNAME(), constants.getSOAPPASSWORD(), "", "");
        transport.debug = true;

        try
        {
            transport.call(SOAP_ACTION, envelope);
            Log.d("XML", transport.requestDump);
            Log.d("XML", transport.responseDump);
            return "Soap successful!";
        }
        catch(Exception e)
        {
            Log.e("EXCEPTION", " " + e.toString());
            return "Error!";
        }
    }

    protected void onPostExecute(String results)
    {
        Log.d("XML", "Pre execute: " + results);
    }

    public void setEwsId(String id)
    {
        ewsId = id;
    }
}


Nu krijg ik de volgende Log incl exception:
11-03 14:01:43.049 21634-21634/hcrt.nl.solutioncenter D/ViewRootImpl: ViewPostImeInputStage ACTION_DOWN
11-03 14:01:43.209 21634-21931/hcrt.nl.solutioncenter I/System.out: Thread-24751(ApacheHTTPLog):Reading from variable values from setDefaultValuesToVariables
11-03 14:01:43.209 21634-21931/hcrt.nl.solutioncenter I/System.out: Thread-24751(ApacheHTTPLog):isSBSettingEnabled false
11-03 14:01:43.209 21634-21931/hcrt.nl.solutioncenter I/System.out: Thread-24751(ApacheHTTPLog):isShipBuild true
11-03 14:01:43.209 21634-21931/hcrt.nl.solutioncenter I/System.out: Thread-24751(ApacheHTTPLog):SMARTBONDING_ENABLED is false
11-03 14:01:43.209 21634-21931/hcrt.nl.solutioncenter I/System.out: Thread-24751(ApacheHTTPLog):SmartBonding Enabling is false, SHIP_BUILD is true, log to file is false, DBG is false
11-03 14:01:43.409 21634-21931/hcrt.nl.solutioncenter I/System.out: AsyncTask #1 calls detatch()
11-03 14:01:43.409 21634-21931/hcrt.nl.solutioncenter E/EXCEPTION: java.lang.NullPointerException: println needs a message
11-03 14:01:43.409 21634-21634/hcrt.nl.solutioncenter D/XML: Pre execute: Error!

[ Voor 83% gewijzigd door Tripwire999 op 03-11-2015 14:24 ]


Acties:
  • 0 Henk 'm!

  • kluyze
  • Registratie: Augustus 2004
  • Niet online
Ik snap de exception niet zo goed, maar ik vermoed dat transport.responseDump null is of zo. Kan je nergens uit je response een http code halen?

Waarom maak je er een NtlmTransport van? Gebruikt de server NTLM Authentication dan? Is het niet gewoon Basic Authentication dat je moet gebruiken?
http://stackoverflow.com/a/7576428

Acties:
  • 0 Henk 'm!

  • Tripwire999
  • Registratie: Januari 2004
  • Laatst online: 10-10 20:19
Uiteindelijk gelukt, ik heb het volgende gedaan:

Ik heb op de website van EasyWSDL van mijn WSDL Android classes gegenereerd. In de execute van de gegenereerde classes heb ik NTLM authenticatiie toegepast. Hierdoor kon ik credentials toepassen op de connectie en niet in de header van de SOAP request zelf.
Voor de NTLM authenticatie was het wel nodig om een extra lib toe te voegen:
ksoap2-extra-ntlm-3.6.0.jar

Duurde even maar dan heb je ook wat al moet ik zeggen dat het op Android een stuk lastiger was dan ik had verwacht 8)7

[ Voor 13% gewijzigd door Tripwire999 op 11-11-2015 13:43 ]

Pagina: 1