Ausgabe
in der Facebook -Validierungsdokumentation
Bitte beachten Sie, dass wir die Signatur unter Verwendung einer maskierten Unicode-Version der Nutzdaten mit Hexadezimalziffern in Kleinbuchstaben generieren. Wenn Sie nur mit den decodierten Bytes rechnen, erhalten Sie am Ende eine andere Signatur. Beispielsweise sollte die Zeichenfolge äöå zu \u00e4\u00f6\u00e5 maskiert werden.
Ich versuche, einen Unittest für die Validierung zu machen, die ich habe, aber ich scheine nicht in der Lage zu sein, die Signatur zu produzieren, weil ich der Nutzlast nicht entkommen kann. ich habe es versucht
mb_convert_encoding($payload, 'unicode')
Aber dies codiert die gesamte Nutzlast und nicht nur die benötigte Zeichenfolge, wie es Facebook tut.
Mein vollständiger Code:
// on the unittest
$content = file_get_contents(__DIR__.'/../Responses/whatsapp_webhook.json');
// trim whitespace at the end of the file
$content = trim($content);
$secret = config('externals.meta.config.app_secret');
$signature = hash_hmac(
'sha256',
mb_convert_encoding($content, 'unicode'),
$secret
);
$response = $this->postJson(
route('whatsapp.webhook.message'),
json_decode($content, true),
[
'CONTENT_TYPE' => 'text/plain',
'X-Hub-Signature-256' => $signature,
]
);
$response->assertOk();
// on the request validation
/**
* @var string $signature
*/
$signature = $request->header('X-Hub-Signature-256');
if (!$signature) {
abort(Response::HTTP_FORBIDDEN);
}
$signature = Str::after($signature, '=');
$secret = config('externals.meta.config.app_secret');
/**
* @var string $content
*/
$content = $request->getContent();
$payloadSignature = hash_hmac(
'sha256',
$content,
$secret
);
if ($payloadSignature !== $signature) {
abort(Response::HTTP_FORBIDDEN);
}
Lösung
Konvertiert zum einen mb_convert_encoding($payload, 'unicode')
die Eingabe in UTF-16BE, nicht UTF-8. Du würdest wollen mb_convert_encoding($payload, 'UTF-8')
.
Zweitens führt die Verwendung mb_convert_encoding()
ohne Angabe der Quellcodierung dazu, dass die Funktion davon ausgeht, dass die Eingabe die Standardcodierung des Systems verwendet, was häufig falsch ist und dazu führt, dass Ihre Daten verstümmelt werden. Du würdest wollen mb_convert_encoding($payload, 'UTF-8', $source_encoding)
. [Außerdem können Sie die Zeichenfolgencodierung nicht zuverlässig erkennen, Sie müssen wissen, was es ist.]
Für drei mb_convert_encoding()
ist es völlig falsch, die gewünschten Escape-Sequenzen auf die Daten anzuwenden. [und mein Gott, sind die Google-Ergebnisse für “php escape UTF-8” schrecklich ]
Leider hat PHP keine UTF-8-Escape-Funktion, die nicht in eine andere Funktion eingebettet ist, aber es ist nicht besonders schwierig, sie im Userland zu schreiben.
function utf8_escape($input) {
$output = '';
for( $i=0,$l=mb_strlen($input); $i<$l; ++$i ) {
$cur = mb_substr($input, $i, 1);
if( strlen($cur) === 1 ) {
$output .= $cur;
} else {
$output .= sprintf('\\u%04x', mb_ord($cur));
}
}
return $output;
}
$in = "asdf äöå";
var_dump(
utf8_escape($in),
);
Ausgabe:
string(23) "asdf \u00e4\u00f6\u00e5"
Beantwortet von – Sammitch
Antwort geprüft von – Mildred Charles (FixError Admin)