parse von json ausgabe für online software-authentifizierung

  • Hallo zusammen,

    ich bin gerade dabei eine verifizierung/authentifikation per https in meine Software zu implementieren.
    Als normaler get-request mit binary ausgabe funktioniert dies auch ganz gut, meine verifizierung sieht (im augenblick noch vereinfacht) gekürzt so aus :


    AutoIt
    Func verifygame($software, $ver, $serial, $mail)
    	Return authkey(getauth($software, $ver, $serial, $mail)
    EndFunc


    Ich sende GET-request zum authserver, authserver antwortet mit $serial,hexedmessageoftheday
    Funktioniert perfekt.

    Da ich in meiner produktiven umgebung jedoch auf meinen get-request eine schön geordnete antwort im json Format bekomme :
    [Blockierte Grafik: http://puu.sh/pvVul/a03fa232a0.png]

    {"activated":true,"instance":"E7A54398B8391F996....","activation_extra":816,"message":"999999999 out of 999999999 activations remaining","timestamp":1466122833}


    zerbreche ich mir den Kopf über eine implementierung.
    Mein höchste priorität : func authkey so anpassen, dass die verifizierung der Software über json klappt.
    Sobald ich dies geschafft habe steht folgendes auf meiner to-do : func timestamp realisieren (im augenblick noch nicht kritisch).

    Lösungsansätze :


    a) Den Input mit regex strippen bis nurnoch mein gewünschter Input übrig bleibt. Ist mir leider nicht gelungen :(


    b) einsetzen eines json parsers
    Dies habe ich probiert anhand von a non strict json udf

    Download hier


    Hatte die Funktion aus meinem Script auf der Suche nach anderen Möglichkeiten entfernt und jetzt beim nachstellen meines Versuchs einen syntaxfehler in den json string eingebaut den ich gerade nicht sehe .. hat aber ohnedies nicht funktioniert.
    Mir ist aber leider auch zuvor kein vernünftiger output mit dem json parser gelungen


    Hat vielleicht jemand eine Idee wie ich mein Ziel realisiere?

    4 Mal editiert, zuletzt von Mentis (17. Juni 2016 um 15:54)

  • Ist zwar quick and dirty, aber wie wäre es hiermit?

    AutoIt
    #include <Array.au3>
    $sJSON = '{"activated":true,"instance":"E7A54398B8391F0","activation_extra":816,"message":"999999999 out of 999999999 activations remaining","timestamp":1466122833}'
    
    
    $aMatch = StringRegExp($sJSON, '"(\w+)":([^,\{\}]+),?', 3)
    
    
    _ArrayDisplay($aMatch)

    Und am Ende deines JSON war ne Klammer und ein Anführungszeichen zu viel...

    LG
    Christoph :)

  • Vielen Dank, genau dieses stripping ist mir nicht gelungen!

    Sieht eigentlich wirklich gut aus, eine (noob)Frage hätte ich noch :
    Wie passe ich denn eine variable aus dem array (in dem fall 0 für die authentifizierung, 5 für den timestamp) in eine function?


    Ich strebe eine, etwa so wie im "pseudocode" dargestellte implementierung an.
    Bin ich da komplett auf dem Holzweg?


    /edit :

    Bin ein paar Schritte weiter gekommen :
    Sollte das so klappen? Irgendwie haperts bei mir noch



    LG Mentis

    Einmal editiert, zuletzt von Mentis (17. Juni 2016 um 19:07)

  • Hi,

    Wie passe ich denn eine variable aus dem array (in dem fall 0 für die authentifizierung, 5 für den timestamp) in eine function?

    Ich weiß nicht wirklich was du erreichen willst ?(
    Du willst eine "variable aus dem array" in eine Funktion passen?

    Meinst du vielleicht:
    Wie gebe ich ein Element des Arrays als Rückgabewert der Funktion getauth() aus?
    Oder:
    Wie füge ich das von Christopf54 erstellte RegEx-Pattern in meinen Code ein?

    Zudem kann ich in deinem pseudocode nicht wirklich viel anfangen.

    Edit:
    ist $aMatch das ergebniss des RegEx und $sdata der JSON?

    Edit2:

    Bin ein paar Schritte weiter gekommen :
    Sollte das so klappen? Irgendwie haperts bei mir noch

    Was sollte so klappen?
    Wenn du versuchst an ein Element des Arrays zu kommen das kannst du so machen:

    AutoIt
    $Element0 = $aArray[0]
    $Element1 = $aArray[1]
    $Element2 = $aArray[2]


    mfg

    Zeitriss

    2 Mal editiert, zuletzt von Zeitriss (17. Juni 2016 um 19:20)

  • Danke fürs gute formulieren meiner Frage ^^ -
    Wie füge ich das von Christopf54 erstellte RegEx-Pattern in meinen Code ein?

    Welche Funktion das Ganze hat : Wenn der Wert "True" in der Json-Ausgabe des Servers erkannt wird triggert sich die aktivierung meiner software.


    $out enthält nichts und wird erst durch "$out = _ArrayToString($aMatch, @TAB, 0, 0)" definiert .. falls mich jetzt nicht alles täuscht


    /edit auf dein edit :

    Exakt :
    $sdata ist der Json.
    $aMatch das ergebniss des RegEx

    Habe ich mich hier verdacht? :

    $datafinal = $aMatch[0]

    2 Mal editiert, zuletzt von Mentis (17. Juni 2016 um 19:42)

  • bei dem String:
    '{"activated":true,"instance":"E7A54398B8391F0","activation_extra":816,"message":"999999999 out of 999999999 activations remaining","timestamp":1466122833}'

    $aMatch[0] = "activated"
    $aMatch[1] = true
    $aMatch[2] = "instance"

    wäre dann nicht $aMatch[1] das gesuchte?

  • Ach das ist natürlich richtig.. hatte einen bösen denkfehler drin...sehr bitter(und peinlich)
    Mir ist bewusst, dass es sicher keine schöne Lösung ist, aber denkst du sollte

    $datafinal = $aMatch[1]
    $out = BinaryToString($datafinal)

    theorethisch funktionieren?

  • Wenn ich das Script richtig verstanden habe dann nicht.
    Du musst den JSON der als Binär heruntergeladen wird in einen String umwandeln befor er mit StringregExp bearbeitet wird.

    Ich habe einfachmal eine Funktion gebaut, wo der JSON schon drin ist.

    Diese Funktion gibt als Rückgabe wert immer True, also den "activated" Wert, des "Beispiel JSON".

    Vielleicht hilft es dir etwas.

    mfg

    Zeitriss

  • Werde mal direkt versuchen das ganze anhand deines Beispiels umzusetzen.
    Wenn es gelingt wäre es exakt was ich versuche fürs erste zu erreichen.


    vielen dank, weiß ich extrem zu schätzen! Hänge an diesem Problem schon einige Zeit ..

  • Dank Christoph und ganz besonders Zeitriss konnte ich sehr große Schritte richtung fertigstellung des Projekts machen.


    Der erste Part funktioniert nun. $aData[1] kann erfolgreich gelesen und weiterverarbeitet werden :).

    Eine letztes Problem habe ich noch :


    Wie implementiere ich am besten eine ausgabe der Werte von getauth() an authkey()?
    authkey() soll

    a) den Wert von $aData[1] mit $match vergleichen
    b) den Wert von $aData[3] als $daymessage ausgeben

    Da eine function nur einen Wert haben kann müsste man meine benötigten werte als array oder byref ausgeben, richtig? Was ich habe und irgendwie nicht funktioniert :( :


    Json :
    {"activated":true,"msg":"Aktivierung Erfolgreich","instance":"E7A54398B8391F9FE19D370","activation_extra":816,"message":"999999999 out of 999999999 activations remaining","timestamp":1466205273}


    /edit so, guten morgen allerseits, ausgeschlafen arbeitet es sich doch immer gleich besser! Drübergedited


    /edit 14:00 .. entweder man ist erfahren und effizient oder alternativ unnachgiebig :p .. 6 stunden Tüftelei später und es läuft :)



    Letzte hürde : Ich bekomme als ausgabe von $data entweder ein array mit 12 werten (aktivierung success) oder ein array mit 8 werten (aktivierung fail) zurück.
    Kommt ein array mit 12 werten -> alles läuft wie erwartet.
    Kommt ein array mit 8 werten -> Scripterror mit crash - "Subscript used on non-accesible variable."


    Insofern in getauthkey folgendes eingebaut :

    If IsArray($aData) or UBound($aData) <> 12 Then
    Return $aData
    ElseIf IsArray($aData) or UBound($aData) <> 8 Then
    Return "Already activated"
    EndIf

    funktioniert. Ist die Lösung eurer wesentlich besseren Meinung nach in Ordnung?

    16 Mal editiert, zuletzt von Mentis (18. Juni 2016 um 14:02)

  • Ist die Anzahl der Werte denn konstant (Fehlerfall mal ausgenommen) und in allen Fällen in der selben Reihenfolge?

    Edit:

    Folgendes sollte natürlich noch raus:

    Spoiler anzeigen
    AutoIt
    Local $ydata = StringToBinary('{"activated":trsue,"instance":"E7A54398B8391F0","activation_extra":816,"message":"999999999 out of 999999999 activations
    AutoIt
    ; Sollte dem Return von InetGet ensprechen (also der JSON im Binärformat)

    Als Returnwert sollte im Fehlerfall keinen String zurück geben, sonder lieber eine dieser Varrianten benützen:

    AutoIt
    Return SetError(1,0,-1); Setzt @error auf 1 und gibt -1 zurück
    Return SetError(1); Setzt @error auf 1
    Return -1
    Return False

    Einmal editiert, zuletzt von Zeitriss (18. Juni 2016 um 14:42)

  • Ja, man bekommt immer entweder 8(bei fail) oder 12(bei success) ausgegeben, inhalt natürlich immer gleich arrangiert.

    /e der return wird dem User in einer Messagebox ausgegeben, aus dem grund habe ich einen String gewählt.

    5 Mal editiert, zuletzt von Mentis (18. Juni 2016 um 16:17)

  • Hey zusammen, wollte es zwar diesmal mit meinem neu gewonnenem wissen komplett eigenständig zusammen bringen .. nur irgendwie bin ich zu doof.

    Bin nun sogut wie fertig, nur leider auf ein Problem gestoßen von dem ich mir nicht gedacht hätte, dass es eines sein wird :(.
    Ich habe noch einen verschachtelten json string den ich verarbeiten muss :

    Code
    {"status_check":"active","status_extra":{"order_key":"wc_order_5763259bf2f37_am_nKIYjWHixLj8","instance":"axdlj3klhgjj4","product_id":"fish","activation_time":"2016-06-19 13:13:41","activation_active":1,"activation_domain":"","software_version":"","status_check":"active"},"activations_remaining":"999999999 out of 999999999 activations remaining"}

    Insgesamt 19 Werte(?)


    relevant wären die Werte active und 1
    von
    status_check=active / activation_active=1


    Insofern bin ich davon ausgegangen, dass :


    funktionieren sollte und meine gewünschten werte in $aData[1] (active) und $aData[13] (1) zu finden sind. Ultimativ werde ich einen der beiden Werte überprüfen.

    Meine Funktion

    gibt mir jedoch immer ein "Login Failed" aus.
    Meine letzte Idee wäre es ein StringLeft($sData, 24) einzubauen (mit ubound auf 2) um nur die ersten 2 Werte auszulesen, aber auch das hat mir ein Login failed ausgegeben :/ ..

    5 Mal editiert, zuletzt von Mentis (19. Juni 2016 um 21:09)

  • Hi,

    Sieh dir mal mit _arraydisplay das Array $loginkey an.

    Wenn ich mich nicht Irre sollte da nicht active drinstehen sondern "active" oder?

    versuch es mal so:

    AutoIt
    $match = '"active"'

    mfg

    Zeitriss

  • Unglaublich aber wahr, das wars!

    [Blockierte Grafik: http://puu.sh/pyCU6/56168cb315.jpg]


    [Blockierte Grafik: http://puu.sh/pyCqz/e557f3952d.png]

    An meinen Debugging(un)künsten muss ich noch viel arbeiten.
    Wenn du wüsstest wie lange ich mir über diese "Kleinigkeit" den Kopf zerbrochen habe.

    Das du dir Gedanken über meine, offensichtlich für die meisten hier Lachhaften, Probleme gemacht hast rechne ich dir wirklich sehr sehr hoch an und bin mehr als nur endlos dankbar.
    Ich hoffe ich bekomme irgendwann mal die Chance mich zu revangieren!