JSON API

PHP Newsletter Software/Script und E-Mail-Marketing Software SuperWebMailer

Moderator: mirko

Antworten
Benutzeravatar
mirko
Beiträge: 21962
Registriert: 25.11.2001, 15:14
Wohnort: Leipzig
Kontaktdaten:

Re: JSON API

Beitrag von mirko » 10.08.2017, 17:21

Gut die 2 Header-Einträge kommen rein. Beim * bei Access-Control-Allow-Origin bleibt es, denn man könnte nur global, also für die komplette SuperWebMailer-Installation, die Domains festlegen. Beim HTTP OPTIONS-Aufruf durch den Browser selbst, wird APIToken nicht übermittelt, damit weiß er nicht, welcher Nutzer das ist.

Nachtrag: Die Aufrufe per JavaScript sollte man nicht nutzen, weil der APIKey sichtbar ist, wenn dann nur für interne Zwecke im Intranet oder auf Webseiten, auf die nicht jeder Zugriff hat. Ansonsten immer ein PHP-Script dahinter legen, dieses per JavaScript ansprechend, falls JavaScript unbedingt notwendig ist.

Thomas Wittich
Beiträge: 51
Registriert: 05.05.2012, 16:05

Re: JSON API

Beitrag von Thomas Wittich » 10.08.2017, 15:29

Hallo Mirko,

ein befreundeter Programmierkollege konnte es aufklären.

So Leid es mir tut, aber das Problem liegt tats. am Server.

Dieser muss mitsenden (immer):

Code: Alles auswählen

@header("Access-Control-Allow-Origin: *");
@header("Access-Control-Allow-Headers: APIToken, apitoken");
Ich habe das in api_json.php nach Zeile 32 eingefügt. Damit es immer mitkommt.

Wie bereits geschrieben, ist "Access-Control-Allow-Origin: *" nötig, um mitzuteilen, welche Hosts (mit Protokoll) erlaubt sind. Die Angabe "*" IST erlaubt, aber natürlich eine schlechte Lösung. Ich will ja nicht, dass jeder von überall aus die JSON-API meiner SWM-Instanz nutzen kann. Schliesslich ist das API-Token ja im JS-Sourcecode sichtbar..... :(

Daher, bitte, im Profil der Admin- und Superadmin-User ein weiteres Feld "API Access-Control-Allow-Origin" erweitern, wo alle zulässigen Hosts gelistet werden können. Das zusammen mit APIToken erreicht eine ausreichende Sicherheit.

Dann fehlte nur noch der "Access-Control-Allow-Header": Dieser MUSS bei der Option-Response (Preflight) mitgesendet werden, SONST geht der ganze Request nicht durch und fällt auf die Nase. Damit wird der benutzerdefinierte Header "APIToken" als zulässig deklariert und beim anschliessenden POST-Request auch durchgewinkt.

Diese Zeile fehlt schlicht und ergreifend in der api_json.php.

Mit diesen zwei zusätzlichen Zeilen funktioniert die ganze Schoße, sowohl mit FF als auch mit Chrome.

Bitte in der nächsten Version berücksichtigen, ich Update regelmäßig und möchte meine eigenen Änderungen nicht verlieren.


Ich frage mich nun, wie ich nun die Halbtage an AJAX-CORS-Forschung verbuchen soll... Jedenfalls nix für ungut - mir wäre es nur ein Anliegen, dass der Fehler berücksichtigt wird, bitte.


VIele Grüße, Sam

Benutzeravatar
mirko
Beiträge: 21962
Registriert: 25.11.2001, 15:14
Wohnort: Leipzig
Kontaktdaten:

Re: JSON API

Beitrag von mirko » 10.08.2017, 11:41

nicht erlaubt ist:

Access-Control-Allow-Origin: *

es muss anstatt * immer eine Domain sein.

Beschäftigt habe ich mich damit auch nicht, wenn dann probieren wie es unter https://stackoverflow.com/questions/126 ... aders-work beschrieben ist.

im eigenen Request den Header Access-Control-Allow-Origin: http://domain.com setzen und auch noch Access-Control-Allow-Credentials: true

Thomas Wittich
Beiträge: 51
Registriert: 05.05.2012, 16:05

Re: JSON API

Beitrag von Thomas Wittich » 10.08.2017, 09:37

Hallo Mirko, hallo alle anderen,

der Aufruf, den JQuery oder der Browser (je nach Browser auch noch unterschiedlich) generieren, unterscheidet sich tatsächlich bei X-Server-Calls und selben Server-Call.

Beim X-Server-Call erhalte ich unter keinen Umständen den Header APIToken, obwohl derselbe im Aufruf zum selben Server vorhanden ist.

Mein letzter Post beschreibt es sehr gut: die rote Zeile des X-Server-Calls hat zwar "apitoken" als erlaubte Headerangabe in "Access-Control-Request-Headers" enthalten, aber das Token selbst fehlt. Das Token selbst ist beim selben-Server-Aufruf enthalten, die grüne Zeile.

Ich habe noch sehr viel getestet und probiert, auch Wireshark mittracen lassen, da ich irgendwann der Browseranzeige/Netzwerk nicht mehr getraut habe. Dort sehe ich dasselbe Ergebnis.

Ich habe auch viel im Netz recherchiert, der von mir gepostetet Code sollte genau das machen. Im Headerbereich gibt es zwei Varianten vom Ajax-Call:
* mit Eigenschaft "header"
* mit Eigenschaft beforeSend und Funktion xhr.setRequestHeader()

Bei liefern bei beiden Calls dasselbe Ergebnis.

Der Witz ist:
Firefox läßt das Bearbeiten und Nochmalsenden eines Requests im Netzwerkmodul zu. Füge ich dort manuell den Header APIToken ein, geht der Call plötzlich durch....
Nur, wie bringe ich per JS den Header dort tatsächlich rein?

Gibt es noch eine andere Authentifizierungsmethode?

Herzlichen Dank für jegliche etwaige Hinweise & Tipps!!

Viele Grüße
Sam

Thomas Wittich
Beiträge: 51
Registriert: 05.05.2012, 16:05

Re: JSON API

Beitrag von Thomas Wittich » 09.08.2017, 12:49

Hallo Mirko,

in der Hilfe von SWM war ja ein Codebeispiel. Das geht nun. Sorry, das hatte ich nicht gesehen.

Nun habe ich ein anderes Problem - bzw. gleich zwei:

api_json.php antwortet ohne Access-Control-Allow-Origin-Header. Ich habe dazu nach api_json.php:193 diese Zeile eingefügt:

Code: Alles auswählen

@header("Access-Control-Allow-Origin: *");
Ist natürlich nicht schön, weil damit jeder auf die API zugreifen könnte.
Es ist ein neuer Feature-Request, die dort erlaubten Sites beim Admin- und Superadmin-User eintragen zu können.

Mit der obigen Zeile kann ich auch von anderen Servern die API ansprechen.

Nun das 2. Problem:

Aus irgendeinem Grund weicht der Header bei dem entfernten Server von dem lokalen Server ab. (lokaler Server: Webserver, wo sowohl SWM installiert ist als auch der JS-JSON-API-Reqeust abgesetzt wird.)

Der entfernte Server macht (Auszug Request-Headers):
Accept:*/*
Accept-Encoding:gzip, deflate
Accept-Language:de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
Access-Control-Request-Headers:apitoken
Access-Control-Request-Method:POST
Cache-Control:no-cache
Connection:keep-alive
Der "lokale" Server macht:
Accept:*/*
Accept-Encoding:gzip, deflate
Accept-Language:de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
APIToken:94c0b0950c62c6869085e7401030fec9
Cache-Control:no-cache
Connection:keep-alive
Ich weiss nicht, weshalb das API-Token plötzlich als Name bei Access-Control-Request steht; das ist sicherlich richtig, allerdings fehlt der Header mit APIToken.

Firefox meldet ausserdem zurück:
Request header field APIToken is not allowed by Access-Control-Allow-Headers in preflight response.
=> Dazu kann ich nichts sagen, verstehe nicht, wieso sich die Meldung auf die Response bezieht, wieso auf die Preflight-Version davon und wieso sie sich auf Access-Control-Allow-Headers bezieht, während der Request ja Access-Control-Request-Headers enthielt.

Vielleicht / hoffentlich kannst Du mir noch einmal weiterhelfen!?!

Herzlichen Dank,

Sam

Benutzeravatar
mirko
Beiträge: 21962
Registriert: 25.11.2001, 15:14
Wohnort: Leipzig
Kontaktdaten:

Re: JSON API

Beitrag von mirko » 09.08.2017, 11:20

Selbst testen, was genau übermittelt wird. Im Browser mit F12 Developer Tools aufrufen, unter Netzwerk kann man die AJAX Hintergrund-Aufruf aufzeichnen lassen und dann sieht man genau was übermittelt wird. Am besten aus meiner Hilfe http://newsletter-software-php-script.s ... on_api.htm das JavaScript-Beispiel verwenden, den Aufruf in den DeveloperTools anschauen und mit dem eigenen Aufruf vergleichen.

Thomas Wittich
Beiträge: 51
Registriert: 05.05.2012, 16:05

Re: JSON API

Beitrag von Thomas Wittich » 09.08.2017, 10:16

Hi Mirko,
ich habe das Script geändert nach Deiner Regel:

Code: Alles auswählen

<!DOCTYPE html>
<html>
<head>
<meta name="generator" content=
"HTML Tidy for HTML5 for Windows version 5.0.0.RC1">
<script src="http://code.jquery.com/jquery-3.2.1.min.js" integrity=
"sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin=
"anonymous">
</script>
<script type="text/javascript">
    function signup() {
      var APIToken = 'abcdef';

			/* Test API */
      jQuery.ajax({
        type: "POST",
        url: "http://www.domain.net/superwebmailer/api/api_json.php",
        beforeSend: function(request) {
          request.setRequestHeader('APIToken',APIToken);
          request.setRequestHeader("Accept", "application/json; charset=utf-8");
//          request.setRequestHeader("Content-Type", "text/html; charset=utf-8");
          request.setRequestHeader("Content-Type", "application/json; charset=utf-8");
        },
        data: {
//					"api_Common__api_testAPI":
					"api_Common__api_testAPI":JSON.stringify( {} )
        },
        dataType: "json",
	      success: function (response) {
	        if (response.error) {
	        	alert("Error: "+response.error+"\nError-Code"+response.error_code);
	        } else {
	        	alert("Success: "+response);
	        }
	        
	      },
	      error: function (xhr, ajaxOptions, thrownError) {
	        alert(xhr.status);
	        alert(thrownError);
	      }
      });
</script>
<title></title>
</head>
<body>
<a href="#" onclick="signup()">signup</a>
</body>
</html>
Das Ergebnis ist noch das gleiche. Siehe Screenshot.

Die Meldung hatte ich vorher natürlich auch gesehen. Aber genau die Meldung sagt mir, dass ich ein falsches Format raussende, nachdem ich 5 x geschaut habe, dass die Methode & Methodenschreibweise "__" statt "." auch passt.

Hast Du noch eine Idee?

Vielen Dank,
Thomas
Dateianhänge
swm-json-api-error.jpg
Fehlermeldung
swm-json-api-error.jpg (12.63 KiB) 612 mal betrachtet

Benutzeravatar
mirko
Beiträge: 21962
Registriert: 25.11.2001, 15:14
Wohnort: Leipzig
Kontaktdaten:

Re: JSON API

Beitrag von mirko » 08.08.2017, 18:21

er findet api_Common__api_testAPI nicht, er sagt ja auch "No valid method found".

"api_Common__api_testAPI":""

ändern in

"api_Common__api_testAPI":JSON.stringify( {} )

Thomas Wittich
Beiträge: 51
Registriert: 05.05.2012, 16:05

JSON API

Beitrag von Thomas Wittich » 08.08.2017, 14:26

Hallo Mirko,
mich bröselt es gerade bei der JSON-api per JS.

Es wäre super, wenn Du ein winziges JS-Beispiel für die JSON-Api hättest....

Meines ist hier:

Code: Alles auswählen

<!DOCTYPE html>
<html>
<head>
<meta name="generator" content=
"HTML Tidy for HTML5 for Windows version 5.0.0.RC1">
<script src="http://code.jquery.com/jquery-3.2.1.min.js" integrity=
"sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin=
"anonymous">
</script>
<script type="text/javascript">
    function signup() {
      var APIToken = 'abcdef';

			/* Test API */
      jQuery.ajax({
        type: "POST",
        url: "http://www.domain.net/superwebmailer/api/api_json.php",
        beforeSend: function(request) {
          request.setRequestHeader('APIToken',APIToken);
          request.setRequestHeader("Accept", "application/json; charset=utf-8");
//          request.setRequestHeader("Content-Type", "text/html; charset=utf-8");
          request.setRequestHeader("Content-Type", "application/json; charset=utf-8");
        },
        data: {
					"api_Common__api_testAPI":""
        },
        dataType: "json",
	      success: function (response) {
	        if (response.error) {
	        	alert("Error: "+response.error+"\nError-Code"+response.error_code);
	        } else {
	        	alert("Success: "+response);
	        }
	        
	      },
	      error: function (xhr, ajaxOptions, thrownError) {
	        alert(xhr.status);
	        alert(thrownError);
	      }
      });


      jQuery.ajax({
        type: "POST",
        url: "http://www.domain.net/superwebmailer/api/api_json.php",
        beforeSend: function(request) {
          request.setRequestHeader('APIToken',APIToken);
          request.setRequestHeader("Accept", "application/json; charset=utf-8");
//          request.setRequestHeader("Content-Type", "text/html; charset=utf-8");
          request.setRequestHeader("Content-Type", "application/json; charset=utf-8");
        },
        data: {
          api_Recipients__api_createRecipient: {
            apiMailingListId: 39,
            apiData: {u_EMail: 'rotes.bueffelfell@web.de'},
            apiGroupsIds: {0: 1},
            apiUseDoubleOptIn: false 
          }
        },
        dataType: "json",
	      success: function (response) {
	        if (response.error) {
	        	alert("Error: "+response.error+"\nError-Code"+response.error_code);
	        } else {
	        	alert("Success: "+response);
	        }
	        
	      },
	      error: function (xhr, ajaxOptions, thrownError) {
	        alert(xhr.status);
	        alert(thrownError);
	      }
      });
    }
        
</script>
<title></title>
</head>
<body>
<a href="#" onclick="signup()">signup</a>
</body>
</html>
Ich erhalte mit diesem Code derzeit immer:

Code: Alles auswählen

{"xml_api_url":null,"error_code":501,"error":"No valid method found."}
Ich nehme an, dass ich lediglich nicht weiss, wie die Methode richtig in die JSON-Struktur geschrieben werden muss.

Vielen Dank!

Grüße, Sam

Antworten