2015-05-25 14 views
6

Sto tentando di autorizzare una sessione di Last.fm e sto facendo fatica a firmare correttamente una richiesta per una chiave di sessione.Autenticazione con Last.fm in Jquery - Firma del metodo non valida fornita

Continuo a ricevere Invalid method signature supplied Tuttavia, quando eseguo l'hash MD5, credo che la query debba consistere al di fuori di JS, ottengo la stessa firma. Devo includere i dati errati nella stringa, credo, ma non riesco a capire cosa.

So che ci sono alcune altre domande e le ho esaminate tutte per vedere cosa sta andando storto qui, ma giuro che sembra giusto per me.

Questo è l'algoritmo di firma e la chiamata Ajax. Ho provato a lasciare abbastanza dati di esempio.

// 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 
} 

Qualcuno può vedere che mi manca qui? Sono assolutamente perplesso sul motivo per cui questo non sta restituendo un oggetto POSTable correttamente firmato nel formato richiesto here. Grazie per il tuo tempo.

Modifica: non posso ringraziare nessuno per il loro tempo se non ho alcun consiglio! Nessuno ha avuto esperienza con last.fm?

+0

Provare a rimuovere 'data [ 'format'] = 'json';' – George

+0

Grazie, cercherò questo insieme al rispondi sotto – TechnicalChaos

+0

Cheers, anche se leggermente fuori - Ho modificato la mia risposta qui sotto con quello che ho trovato riguardo all'attributo format. – TechnicalChaos

risposta

1

Così il test alcune delle risposte, ho trovato la soluzione. C'erano 2 problemi. EDITED vedi sotto ( Il primo è stato la necessità di dover rimuovere

data['format'] = 'json'; 

come George Lee rilevare. Grazie George. )

L'altro problema era che mi aveva chiamato una variabile in modo non corretto così è stato di essere pubblicati con il nome sbagliatoLa linea

so['signature'] = hashed_sec; 

avrebbe dovuto essere

so['api_sig'] = hashed_sec; 

ho notato questo in risposta di Pankaj ma purtroppo il resto della sua risposta (cioè compreso il metodo) non era corretto. Effettuare queste 2 modifiche ha risolto la chiamata e l'ha firmata correttamente.

Grazie per tutti i suggerimenti!

EDIT: Dopo un po 'di più a giocare, ho trovato che

data['format'] = 'json'; 

sono corrette, tuttavia non ottiene hashing con la firma. Aggiunta di data['format'] = 'json'; all'oggetto POST dopo l'hashing e in questo caso restituirà JSON anziché XML - che era il metodo preferito. L'aggiunta dopo l'hashing non è documentata da nessuna parte che io possa trovare, quindi eccoti. Il nuovo codice di lavoro è la seguente, e questo dimostra le 2 linee indicate con --------------------

// 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

Sì, ho visto da qualche parte nella documentazione dell'API che poteva essere restituito come JSON ma non ho visto da nessuna parte su come farlo. Sono contento che tu abbia risolto tutto! – George

2

Dopo aver esaminato il codice e altri post relativi alla chiamata a last.fm, ho scoperto che @george lee in realtà è corretto. Non è necessario fornire format durante la generazione di auth_sign.

A parte che è necessario applicare $.md5()-auth_sign stringa dopo l'applicazione encodeURIComponent() e unescape() funzioni. Come questo.

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

anche mentre si effettua ajax chiamata è necessario passare api_key, token & api_sig come data. Ma vedendo il tuo codice, rivela che stai passando api_key, token, format, method & signature.

Quindi è necessario rimuovere format, method & signature dal campo data della chiamata ajax.

Invece è necessario passare api_key, token & api_sig nel campo data.

Quindi il codice finale dopo aver commentato la riga data['format'] = 'json'; sarà simile a questo.

// 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

Grazie! Ci proverò il prima possibile e ti farò sapere il risultato. L'ho provato senza il solo metodo, e questo ha generato una risposta XML invece di JSON, ma proverò con gli altri passi e vedremo. – TechnicalChaos

+0

Ancora non ho ancora avuto la possibilità di testarlo. – TechnicalChaos

+0

Grazie per l'aiuto, ho notato un errore nel mio codice grazie all'esempio qui. – TechnicalChaos

Problemi correlati