Получение токена запроса с использованием php в Flickr: oauth_problem = signature_invalid - PullRequest
0 голосов
/ 06 апреля 2020

Исходный вопрос

Я хочу загрузить фотографии на Flickr с помощью PHP, и сначала мне нужно выполнить аутентификацию пользователя с помощью OAuth.

Вот ссылка на api do c:

Сначала вы должны создать базовую строку из вашего запроса. Базовая строка создается путем объединения HTTP-глагола, URL-адреса запроса и всех параметров запроса, отсортированных по имени, с использованием лексикографического упорядочения байтовых значений, разделенных символом «&».

Использование базовой строки в качестве текста и ключ - это объединенные значения Consumer Secret и Token Secret, разделенные знаком '&'.

И согласно эта , tokenSecret является пустой строкой при вызове request_token

Вот мой фрагмент кода:

/**
 * generateSignature
 * @param        $httpVerb
 * @param        $requestUrl
 * @param        $parameters
 * @param string $tokenSecret
 *
 * @return string
 */
function generateSignature($httpVerb, $requestUrl, $parameters, $tokenSecret=''){
    global $consumerSecret;
    ksort($parameters);
    $queryStr = http_build_query($parameters);
    //not urlencode, same error
    //$baseStr = $httpVerb . '&' . $requestUrl . '&' . $queryStr;
    //urlencode
    $baseStr = urlencode($httpVerb . '&' . $requestUrl . '&' . $queryStr);
    $key = $consumerSecret . '&' . $tokenSecret;
    $signature = hash_hmac('sha1', $baseStr, $key, false);
    return $signature;
}

/**
 * getRequestToken
 * @return string
 */
function getRequestToken(){
    global $consumerKey;
    global $callbackUrl;
    $requestTokenURL = 'https://www.flickr.com/services/oauth/request_token';
    $queryParameters = [
        //nonce: temporarily use hard code
        'oauth_nonce' => '83273423',
        'oauth_timestamp' => time(),
        'oauth_consumer_key' => $consumerKey,
        'oauth_signature_method' => 'HMAC-SHA1',
        'oauth_version' => '1.0',
        'oauth_callback' => urlencode($callbackUrl),
    ];
    $queryParameters['oauth_signature'] = generateSignature('GET', $requestTokenURL, $queryParameters);
    $queryStr = http_build_query($queryParameters);
    return $requestTokenURL . '?' . $queryStr;
}

$consumerKey = '<YOUR_CONSUMER_KEY>';
$consumerSecret = '<YOUR_CONSUMER_SECRET>';
$callbackUrl = '<YOUR_REDIRECT_URL>';
$requestTokenURLWithQueryStr = getRequestToken();
// echo $requestTokenURLWithQueryStr;exit;
header('Location: '. $requestTokenURLWithQueryStr);

Но я получил "oauth_problem = signature_invalid" от Flickr, я не знаю, где я не прав, любой, кто знаком с этим можете мне помочь?


Обновление

Ну, во-первых, я должен поблагодарить @CBroe за указание моей неправильной точки, и вот мой код после изменения:

/**
 * generateSignature
 * @param        $httpVerb
 * @param        $requestUrl
 * @param        $parameters
 * @param string $tokenSecret
 *
 * @return string
 */
function generateSignature($httpVerb, $requestUrl, $parameters, $tokenSecret=''){
    global $consumerSecret;
    ksort($parameters);
    $queryStr = http_build_query($parameters);
    $queryStr = urlencode(urldecode($queryStr));
    // echo $queryStr;exit;
    $baseStr = $httpVerb . '&' . urlencode($requestUrl) . '&' . $queryStr;
    echo $baseStr;exit;
    $key = $consumerSecret;
    $signature = hash_hmac('sha1', $baseStr, $key, false);
    return $signature;
}

/**
 * getRequestToken
 * @return string
 */
function getRequestToken(){
    global $oauth_nonce;
    global $oauth_timestamp;
    global $oauth_consumer_key;
    global $oauth_callback;
    $requestTokenURL = 'https://www.flickr.com/services/oauth/request_token';
    $queryParameters = [
        'oauth_nonce' => $oauth_nonce,
        'oauth_timestamp' => $oauth_timestamp,
        'oauth_consumer_key' => $oauth_consumer_key,
        'oauth_signature_method' => 'HMAC-SHA1',
        'oauth_version' => '1.0',
        'oauth_callback' => urlencode($oauth_callback),
    ];
    // var_dump($queryParameters);exit;
    $queryParameters['oauth_signature'] = generateSignature('GET', $requestTokenURL, $queryParameters);
    $queryStr = http_build_query($queryParameters);
    return $requestTokenURL . '?' . $queryStr;
}

$oauth_nonce = '95613465';
$oauth_timestamp = '1305586162';
$oauth_consumer_key = '653e7a6ecc1d528c516cc8f92cf98611';
$oauth_consumer_secret = '*******';
$oauth_callback = 'http://www.example.com';

$requestTokenURLWithQueryStr = getRequestToken();
header('Location: '. $requestTokenURLWithQueryStr);

Сейчас я использую точно такой же параметр, как в примере , и я должен указать на одну вещь, в примере параметр oauth_nonce и oauth_timestamp в «URL» не так же, как их в «базовой строке» ( см. скриншот ниже): enter image description here

Я использую параметр oauth_nonce и oauth_timestamp в "базовой строке", чтобы я мог генерировать точно такую ​​же "базу" string "в качестве примера.

Запустите мой код, и этот оператор echo $baseStr;exit; выведет« базовую строку », она точно такая же, как в примере, верно?

Но даже Я воспроизвожу пример, если я заменю значение параметра ($oauth_nonce, $oauth_timestamp, $oauth_consumer_key, $oauth_consumer_secret, $oauth_callback) своим собственным, то же сообщение об ошибке "signature_invalid". Что мне теперь делать?


Обновление 2

Вот мой обновленный код (конечно, мне пришлось заменить параметры на свои, особенно oauth_consumer_key и oauth_consumer_secret и oauth_callback), но подпись по-прежнему недействительна:

function generateSignature($httpVerb, $requestUrl, $parameters, $tokenSecret=''){
    global $consumerSecret;
    ksort($parameters);
    $queryStr = http_build_query($parameters);
    $queryStr = urlencode($queryStr);
    $baseStr = $httpVerb . '&' . urlencode($requestUrl) . '&' . $queryStr;
    $key = $consumerSecret . '&' . $tokenSecret;
    $signature = hash_hmac('sha1', $baseStr, $key, false);
    return $signature;
}

function getRequestToken(){
    global $oauth_nonce;
    global $oauth_timestamp;
    global $oauth_consumer_key;
    global $oauth_callback;
    $requestTokenURL = 'https://www.flickr.com/services/oauth/request_token';
    $queryParameters = [
        'oauth_nonce' => $oauth_nonce,
        'oauth_timestamp' => $oauth_timestamp,
        'oauth_consumer_key' => $oauth_consumer_key,
        'oauth_signature_method' => 'HMAC-SHA1',
        'oauth_version' => '1.0',
        'oauth_callback' => $oauth_callback,
    ];
    // var_dump($queryParameters);exit;
    $queryParameters['oauth_signature'] = generateSignature('GET', $requestTokenURL, $queryParameters);
    $queryStr = http_build_query($queryParameters);
    return $requestTokenURL . '?' . $queryStr;
}

//official document example paramters
$oauth_nonce = '95613465';
$oauth_timestamp = '1305586162';
$oauth_consumer_key = '653e7a6ecc1d528c516cc8f92cf98611';
$oauth_consumer_secret = '*******';
$oauth_callback = 'http://www.example.com';

$requestTokenURLWithQueryStr = getRequestToken();
// echo $requestTokenURLWithQueryStr;exit;
header('Location: '. $requestTokenURLWithQueryStr);

Обновление 3 (наконец-то я решил эту проблему, благодаря [PHP] Flickr OAuth PHP 認證 小 筆記 Part 2 )

Сохраните следующий код в файл php (скажем, test.php), затем замените параметр oauth_consumer_key, oauth_consumer_secert и oauth_callback на свой, и запустите код, у вас все получится (и, пожалуйста, не верьте официальным API , это полная чушь):

<?php
/**
 * generateSignature
 * @param        $httpVerb
 * @param        $requestUrl
 * @param        $parameters
 * @param string $tokenSecret
 *
 * @return string
 */
function generateSignature($httpVerb, $requestUrl, $parameters, $tokenSecret=''){
    global $oauth_consumer_secret;
    ksort($parameters);
    $queryStr = http_build_query($parameters);
    $baseStr = $httpVerb . '&' . urlencode($requestUrl) . '&' . urlencode($queryStr);
    $key = $oauth_consumer_secret . '&' . $tokenSecret;
    $signature = hash_hmac('sha1', $baseStr, $key, true);
    $signature = urlencode(base64_encode($signature));
    return $signature;
}

/**
 * Get authorization header
 * @return array
 */
function getRequestHeaders(){
    global $oauth_consumer_key;
    global $oauth_callback;
    global $requestTokenURL;
    $queryParameters = [
        'oauth_nonce' => crc32(time()),
        'oauth_timestamp' => time(),
        'oauth_consumer_key' => $oauth_consumer_key,
        'oauth_signature_method' => 'HMAC-SHA1',
        'oauth_version' => '1.0',
        'oauth_callback' => $oauth_callback,
    ];
    // var_dump($queryParameters);exit;
    $queryParameters['oauth_signature'] = generateSignature('GET', $requestTokenURL, $queryParameters);

    //urldecode the oauth_callback url(cause http_build_query() will urlencode it)
    $queryStr = urldecode(http_build_query($queryParameters));

    //replace "&" with ",",and add double quote at the right side of the "=" and the left side of the ",",
    //doing this is because we need to add double quote to the value of the query string, because this string
    //will use as authorization header, not as query string.
    $authorization = str_replace('&', '", ', str_replace('=', '="', $queryStr)) . '"';
    $authorization = 'Authorization: OAuth realm="", ' . $authorization;
    return [$authorization];
}

/**
 * getRequestToken
 * @return array
 */
function getRequestToken(){
    $headers = getRequestHeaders();
    $ch = curl_init();
    curl_setopt ($ch, CURLOPT_URL, 'https://www.flickr.com/services/oauth/request_token');
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, 30);
    curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
    //in case you need a proxy
    //curl_setopt ($ch, CURLOPT_PROXY, 'http://127.0.0.1:1087');
    $returnStr = curl_exec($ch);
    if(curl_errno($ch)){
        echo 'Error: ' . curl_error($ch);
    }
    curl_close($ch);
    $returnArr = [];
    parse_str($returnStr, $returnArr);
    return $returnArr;
}

$requestTokenURL = 'https://www.flickr.com/services/oauth/request_token';

$oauth_consumer_key = '<YOUR_CONSUMER_KEY>';
$oauth_consumer_secret = '<YOUR_CONSUMER_SECERT>';
$oauth_callback = '<YOUR_CALLBACK_URL>';

$tokens = getRequestToken();
var_dump($tokens);

Оказывается, нам нужно передать параметр в заголовок http и официальный API никогда не говори об этом, это сводит меня с ума.

1 Ответ

0 голосов
/ 07 апреля 2020
$baseStr = urlencode($httpVerb . '&' . $requestUrl . '&' . $queryStr);

Не похоже, что вы должны здесь кодировать URL-адрес целиком.

В примере в их документах сказано, что вы должны получить строковое значение типа

GET&https%3A%2F%2Fwww.flickr.com%2Fservices%2F…

Тем не менее, из-за кодировки URL, примененной в указанном выше месте, на данный момент

GET%26https%3A%2F%2Fwww.flickr.com%2Fservices%2F…

.

Вам необходимо кодировать URL части здесь отдельно, а затем соедините их вместе простым & впоследствии.

(Не уверен, если $queryStr нужен уровень кодирования extra здесь, http_build_query должен иметь уже позаботился о правильном кодировании параметров и значений внутри него. Но $requestUrl делает в любом случае.)

...