2015-05-25 55 views
6

我試圖驗證Last.fm會話,並且正努力正確簽署會話密鑰請求。在Jquery中使用Last.fm進行身份驗證 - 提供的方法簽名無效

我不斷收到Invalid method signature supplied但是,當我md5哈希我認爲查詢應該由JS以外組成,我得到相同的簽名。我想必須在字符串中包含錯誤的數據,但無法弄清楚什麼。

我知道還有其他一些問題,我已經通過他們所有人看到這裏出了什麼問題,但我發誓它看起來是對我的。

這是簽名算法和Ajax調用。我試圖留下足夠的樣本數據。

// Set elsewhere but hacked into this example: 
var last_fm_data = { 
    'last_token':'TOKEN876234876', 
    'user': 'bob', 
    'secret': 'SECRET348264386' 
}; 

// Kick it off. 
last_fm_call('auth.getSession', {'token': last_fm_data['last_token']}); 


// Low level API call, purely builds a POSTable object and calls it. 
function last_fm_call(method, data){ 
    // param data - dictionary. 

    last_fm_data[method] = false; 
    // Somewhere to put the result after callback. 

    // Append some static variables 
    data['api_key'] = "APIKEY1323454"; 
    data['format'] = 'json'; 
    data['method'] = method; 
    post_data = last_fm_sign(data); 

    $.ajax({ 
     type: "post", 
     url: last_url, 
     data: post_data, 
     success: function(res){ 
      last_fm_data[method] = res; 
      console.log(res['key'])// Should return session key. 
     }, 
     dataType: 'json' 
    }); 
} 

function last_fm_sign(params){ 
    ss = ""; 
    st = []; 
    so = {}; 
    Object.keys(params).forEach(function(key){ 
     st.push(key); // Get list of object keys 
    }); 
    st.sort(); // Alphabetise it 
    st.forEach(function(std){ 
     ss = ss + std + params[std]; // build string 
     so[std] = params[std]; // return object in exact same order JIC 
    });  
     // console.log(ss + last_fm_data['secret']); 
     // api_keyAPIKEY1323454formatjsonmethodauth.getSessiontokenTOKEN876234876SECRET348264386 
    hashed_sec = unescape(encodeURIComponent($.md5(ss + last_fm_data['secret']))); 
    so['signature'] = hashed_sec; // Correct when calculated elsewhere. 
    return so; // Returns signed POSTable object 
} 

任何人都可以看到我在這裏失蹤?我絕對難住爲什麼這不會以請求的格式here返回正確簽名的POSTable對象。謝謝你的時間。

編輯:如果我沒有得到任何建議,不能感謝任何人的時間!沒有人對last.fm有過任何經驗?

+0

嘗試移除'數據[「格式」] =「JSON」所示的2線;' – George

+0

謝謝,我會與沿嘗試此回答如下。 – TechnicalChaos

+0

乾杯,儘管稍微偏離 - 我已經編輯了我自己的答案,下面是關於format屬性的內容。 – TechnicalChaos

回答

1

所以在測試一些答覆,我找到了解決辦法。有兩個問題。 EDITED見下文( 首先是需要去除

data['format'] = 'json'; 

George Lee指出。感謝喬治。 )

的另一個問題是,我會叫一個變量不正確,因此正在以HTTP POST錯誤的名字。該生產線

so['signature'] = hashed_sec; 

應該已經

so['api_sig'] = hashed_sec; 

我注意到這潘卡的答案,但遺憾的是他的答案(即包括方法)的其餘部分是不正確的。進行這兩項更改可以解決呼叫並正確簽名。

感謝您的所有建議!

編輯: 經過一番更多的上場,我發現

data['format'] = 'json'; 

是正確的,但是它沒有得到與簽名散列。 在散列工作之後將data['format'] = 'json';添加到POST對象,並且在此實例中將返回JSON而不是XML - 這是首選方法。哈希後添加沒有記錄在任何我能找到的地方,所以你去了。 的新的工作代碼如下,這示出了具有--------------------

// Set elsewhere but hacked into this example: 
var last_fm_data = { 
    'last_token':'TOKEN876234876', 
    'user': 'bob', 
    'secret': 'SECRET348264386' 
}; 

// Kick it off. 
last_fm_call('auth.getSession', {'token': last_fm_data['last_token']}); 


// Low level API call, purely builds a POSTable object and calls it. 
function last_fm_call(method, data){ 
    // param data - dictionary. 

    last_fm_data[method] = false; 
    // Somewhere to put the result after callback. 

    // Append some static variables 
    data['api_key'] = "APIKEY1323454"; 
    data['method'] = method; 
    post_data = last_fm_sign(data); 
    // THEN ADD THE FORMAT --------------------------------------- 
    post_data['format'] = 'json'; 
    $.ajax({ 
     type: "post", 
     url: last_url, 
     data: post_data, 
     success: function(res){ 
      last_fm_data[method] = res; 
      console.log(res['key'])// Should return session key. 
     }, 
     dataType: 'json' 
    }); 
} 

function last_fm_sign(params){ 
    ss = ""; 
    st = []; 
    so = {}; 
    Object.keys(params).forEach(function(key){ 
     st.push(key); // Get list of object keys 
    }); 
    st.sort(); // Alphabetise it 
    st.forEach(function(std){ 
     ss = ss + std + params[std]; // build string 
     so[std] = params[std]; // return object in exact same order JIC 
    });  
     // console.log(ss + last_fm_data['secret']); 
     // api_keyAPIKEY1323454formatjsonmethodauth.getSessiontokenTOKEN876234876SECRET348264386 
    hashed_sec = unescape(encodeURIComponent($.md5(ss + last_fm_data['secret']))); 
    so['api_sig'] = hashed_sec; // RENAMED THIS ---------------------------- 
    return so; // Returns signed POSTable object 
} 
+0

是的,我在API文檔的某處看到它可以作爲JSON返回,但沒有看到有關如何執行它的任何地方。很高興你已經把它全部排序! – George

2

在調查了您的代碼和其他與last.fm api調用相關的帖子之後,我發現@george lee其實是正確的。在生成auth_sign時,您不需要提供format

除此之外,您需要申請$.md5()auth_sign字符串後應用encodeURIComponent()unescape()函數。喜歡這個。

hashed_sec = $.md5(unescape(encodeURIComponent(ss + last_fm_data['secret']))); 

而且同時使ajax叫你需要通過api_key, token & api_sigdata。但看到你的代碼,顯示你正在通過api_key, token, format, method & signature

因此您需要從data字段ajax調用中刪除format, method & signature

相反,您需要將api_key, token & api_sig傳遞給data字段。

因此,評論data['format'] = 'json';行後的最終代碼將如下所示。

// Set elsewhere but hacked into this example: 
    var last_fm_data = { 
     'last_token':'TOKEN876234876', 
     'user': 'bob', 
     'secret': 'SECRET348264386' 
    }; 

    // Kick it off. 
    last_fm_call('auth.getSession', {'token': last_fm_data['last_token']}); 


    // Low level API call, purely builds a POSTable object and calls it. 
    function last_fm_call(method, data){ 
     // param data - dictionary. 
     last_fm_data[method] = false; 
     // Somewhere to put the result after callback. 

     // Append some static variables 
     data['api_key'] = "APIKEY1323454"; 
     //data['format'] = 'json'; 
     data['method'] = method; 

     post_data = last_fm_sign(data); 

     $.ajax({ 
      type: "POST", 
      url: last_url, 
      data: post_data, 
      success: function(res){ 
       last_fm_data[method] = res; 
       console.log(res['key'])// Should return session key. 
      }, 
      dataType: 'json' 
     }); 
    } 

    function last_fm_sign(params){ 
     ss = ""; 
     st = []; 
     so = {}; 
     so['api_key'] = params['api_key']; 
     so['token'] = params['token']; 
     Object.keys(params).forEach(function(key){ 
      st.push(key); // Get list of object keys 
     }); 
     st.sort(); // Alphabetise it 
     st.forEach(function(std){ 
      ss = ss + std + params[std]; // build string 
     }); 
     ss += last_fm_data['secret']; 
      // console.log(ss + last_fm_data['secret']); 
      // api_keyAPIKEY1323454formatjsonmethodauth.getSessiontokenTOKEN876234876SECRET348264386 
     hashed_sec = $.md5(unescape(encodeURIComponent(ss))); 
     so['api_sig'] = hashed_sec; // Correct when calculated elsewhere. 
     return so; // Returns signed POSTable object 
    } 

Please refer to this link.

+0

謝謝!我會盡快嘗試,並讓你知道結果。我確實嘗試過,沒有單獨的方法,而是繪製了一個XML響應而不是JSON,但是我會用其他步驟嘗試並看到。 – TechnicalChaos

+0

還有沒有機會測試這一點,但不幸的是。 – TechnicalChaos

+0

感謝您的幫助,我發現代碼中有一個錯誤,這要歸功於此處的示例。 – TechnicalChaos

相關問題