簡體   English   中英

無法使用 Twitter V1.1 API 驗證用戶

[英]Can not authenticate user with Twitter V1.1 API

我已經通過創建簽名實現了一切。 我創建了一個 function 來收集所需的參數(為了清楚起見,我在此處添加了一些注釋):

function collect_parameters(){
    global $credentials; // This is an Object with my App's credentials and stuff

    $oAuth = get_user_oauth();  // This returns an object with the the personal user OAuth tokens retrieved from the earlier docs.
    $encoded_collection = array();

    $collection = array(
        'status'                 => rawurlencode( $_GET['tweet'] ),
        'include_entities'       => 'true',
        'oauth_consumer_key'     => $credentials->key,
        'oauth_nonce'            => $credentials->nonce, // md5( str_shuffle( uniqid() . mt_rand(0,9999999999) ) )
        'oauth_signature_method' => 'HMAC-SHA1',
        'oauth_timestamp'        => $credentials->time, // current timestamp
        'oauth_token'            => $oAuth->oauth_token,
        'oauth_version'          => '1.0',
    );

    // Percent encode every key and value that will be signed.
    foreach( $collection as $key => $value ){
        $encoded_collection[rawurlencode($key)] = rawurlencode($value); 
    }

    // Sort the list of parameters alphabetically by encoded key.
    ksort( $encoded_collection );

    return http_build_query( $encoded_collection );
}

我使用這個 function 來構建簽名基本字符串

function create_signature_base_string( $parameter_string, $url = 'https://api.twitter.com/1.1/statuses/update.json', $method = 'POST' ){
    return strtoupper( $method ) .'&'. rawurlencode( $url ) .'&'. rawurlencode( $parameter_string );
}

我用這個 function 來計算簽名

function calculate_signature( $signature_base_string, $signing_key ){
    return base64_encode( hash_hmac('sha1', $signature_base_string, $signing_key, true) );
}

現在構建 OAuth Header。 這是一個 function ,它使用上面的輔助函數(加上其他一些返回所需信息的函數):

function get_oauth_headers(){
    global $credentials;
    $oAuth = get_user_oauth();
    
    $parameters = collect_parameters();
    $signature_base_string = create_signature_base_string( $parameters );
    $signing_key = get_signing_key();
    $signature = calculate_signature( $signature_base_string, $signing_key );

    $auth_array = array(
        'oauth_consumer_key'     => $credentials->key,
        'oauth_nonce'            => $credentials->nonce,
        'oauth_signature'        => $signature,
        'oauth_signature_method' => 'HMAC-SHA1',
        'oauth_timestamp'        => $credentials->time,
        'oauth_token'            => $oAuth->oauth_token,
        'oauth_version'          => '1.0'
    );

    ksort( $auth_array );

    return $auth_array;
}

現在我已經把所有東西都放在了一個漂亮整潔的小陣列中,是時候實際嘗試將它發送到 Twitter。

function create_tweet( $build_query = true ){
    global $credentials;

    $ch = curl_init();

    $url    = 'https://api.twitter.com/1.1/statuses/update.json';
    $fields = array(
        'status' => rawurlencode( $_GET['tweet'] ) // I've just been using "Test" or "WhyNoWork" style text in this $_GET param
    );

    $oAuth_headers = get_oauth_headers(); // This uses that function above that returns all of the specific parameters for OAuth, sorted, and ready to go.
    $oAuth_array   = array();

    // Loop through the oauth headers, and encode them
    foreach( $oAuth_headers as $key => $value ){
        $oAuth_array[] = rawurlencode($key) .'="'. rawurlencode($value) .'"';
    }

    // Implode it into a single line
    $oAuth_string = implode(', ', $oAuth_array );

    $headers = array(
        'Content-Type: application/x-www-form-rawurlencoded',
        'Authorization: OAuth '. $oAuth_string,
    );

    curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
    curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
    curl_setopt( $ch, CURLOPT_ENCODING, 'gzip' );
    curl_setopt( $ch, CURLOPT_POST, true );
    
    // It seems to prefer this as a query string instead of postfields?
    if( $build_query == true ){
        curl_setopt( $ch, CURLOPT_URL, $url.'?'.http_build_query($fields) );
    } else {
        curl_setopt( $ch, CURLOPT_URL, $url );
        curl_setopt( $ch, CURLOPT_POSTFIELDS, $fields );
    }

    $result = curl_exec( $ch );
    $info   = curl_getinfo( $ch );

    curl_close( $ch );

    if( isset($_GET['debug']) ){
        echo $result;
        var_dump( $info );
    } else {
        echo $result;
    }
}

例如,這是 OAuth header 中所有內容的順序。 我已經運行了我的每個小助手函數十幾次,確保它們采用正確的 arguments 和 output 適當的值。 我什至用文檔中的憑據替換了我自己的 OAuth 憑據,最終得到了與簽名密鑰、簽名等相同的結果:

OAuth 標頭

然而,每次我嘗試運行create_tweet() function 時,我都會收到帶有錯誤 32 的 401 狀態代碼: {"errors":[{"code":32,"message":"Could not authenticate you."}]} . 我到底錯過了什么? 是否有可能看到為什么他們無法驗證請求?


這是來自collect_parameters()的 output ; include_entities=true&oauth_consumer_key=APP_API_KEY&oauth_nonce=ABC123&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1597456781&oauth_token=USER_AUTH_TOKEN&oauth_version=1.0&status=TESTING

這將傳遞給簽名基本字符串 function,該字符串返回以下內容:

POST&https%3A%2F%2Fapi.twitter.com%2F1.1%2Fstatuses%2Fupdate.json&include_entities%3Dtrue%26oauth_consumer_key%3DAPP_API_KEY%26oauth_nonce%3DABC123%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1597457034%26oauth_token%3DUSER_AUTH_TOKEN%26oauth_version%3D1.0%26status%3DTESTING

看起來不錯,現在我使用簽名密鑰: APP_SECRET&USER_AUTH_SECRET並傳遞它們來計算簽名給了我一個值,就像文檔中的那個一樣(並且使用文檔中的參數給了我他們顯示的相同簽名): thIsiSeEmSUnNecEssArYPOs3OxQdSNpI=

我不明白如何用測試數據替換我的數據並獲得相同的結果,但我仍然無法獲得 API 請求身份驗證?

您正在執行一些額外的編碼。

首先,在collect_parameters中,您正在對$encoded_collection數組的鍵和值進行編碼,然后將其傳遞給http_build_query ,這將進一步對它們進行編碼。 您可以完全刪除循環來對項目進行編碼,而是將它們直接傳遞給http_build_query 訣竅在於它默認為+編碼,因此您需要使用第四個參數告訴它切換到%編碼:

function collect_parameters()
{
    global $credentials; // This is an Object with my App's credentials and stuff

    $oAuth = get_user_oauth();  // This returns an object with the the personal user OAuth tokens retrieved from the earlier docs.
    
    $collection = [
        'status' => 'Hello Ladies + Gentlemen, a signed OAuth request!',
        'include_entities' => 'true',
        'oauth_consumer_key' => $credentials->key,
        'oauth_nonce' => $credentials->nonce, // md5( str_shuffle( uniqid() . mt_rand(0,9999999999) ) )
        'oauth_signature_method' => 'HMAC-SHA1',
        'oauth_timestamp' => $credentials->time, // current timestamp
        'oauth_token' => $oAuth->oauth_token,
        'oauth_version' => '1.0',
    ];

    // Sort the list of parameters alphabetically by encoded key.
    ksort($collection);

    return http_build_query($collection, '', '&', PHP_QUERY_RFC3986);
}

接下來,在您的create_tweet function 中,在第一個循環中,您將再次對不需要的鍵和值進行編碼,可以將其刪除:

    foreach ($oAuth_headers as $key => $value) {
        $oAuth_array[] = $key . '="' . $value . '"';
    }

不幸的是,我沒有 Twitter 帳戶來測試所有這些,但是他們的文檔有我能夠使用的示例密鑰和示例 output,並且使用這些更改和文檔產生了相同的 Z78E6221F6393D135CEZF6681。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM