在 Jquery 中使用 Last.fm 进行身份验证 - 提供的方法签名无效
Authenticating with Last.fm in Jquery - Invalid method signature supplied
我正在尝试对 Last.fm 会话进行授权,但正在努力正确地签署会话密钥请求。
我一直收到 Invalid method signature supplied
但是,当我对我认为查询应该包含 JS 之外的内容进行 md5 哈希时,我得到了相同的签名。我猜我一定是在字符串中包含了错误的数据,但不知道是什么。
我知道还有其他一些问题,我已经 运行 仔细检查了所有问题,以了解这里出了什么问题,但我发誓它对我来说是对的。
这是签名算法和 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
}
任何人都可以看到我在这里遗漏了什么?我完全不明白为什么这没有以请求的格式返回正确签名的 POSTable 对象 here。谢谢你的时间。
编辑:如果我没有得到任何建议,就无法感谢任何人的宝贵时间!没有人使用过 last.fm?
在调查了您的代码和其他与 last.fm
api 调用相关的帖子后,我发现 @george lee 实际上是正确的。生成 auth_sign
时无需提供 format
。
除此之外,您需要在应用 encodeURIComponent()
和 unescape()
函数后将 $.md5()
应用到 auth_sign
字符串。像这样。
hashed_sec = $.md5(unescape(encodeURIComponent(ss + last_fm_data['secret'])));
此外,在进行 ajax
调用时,您需要将 api_key, token & api_sig
作为 data
传递。但是看到你的代码,表明你正在传递 api_key, token, format, method & signature
.
因此您需要从 ajax
调用的 data
字段中删除 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
}
因此,在测试了一些回复后,我找到了解决方案。有两个问题。
编辑见下文(
第一个是需要删除
data['format'] = 'json';
正如 George Lee 指出的那样。谢谢乔治。
)
另一个问题是我错误地命名了一个变量,因此 POST 使用了错误的名称。该行
so['signature'] = hashed_sec;
应该是
so['api_sig'] = hashed_sec;
我在 Pankaj 的回答中注意到了这一点,但不幸的是他的其余回答(即包括方法)不正确。进行这两项更改解决了调用并正确签名。
感谢所有建议!
编辑:
玩了几次之后,我发现
data['format'] = 'json';
是正确的,但它没有与签名一起散列。
在散列后将 data['format'] = 'json';
添加到 POST 对象,在这种情况下将 return JSON 而不是 XML - 这是首选方法。在我能找到的任何地方都没有记录散列后添加,所以你去吧。
新的工作代码如下,这显示了用 --------------------
指示的 2 行
// 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
}
我正在尝试对 Last.fm 会话进行授权,但正在努力正确地签署会话密钥请求。
我一直收到 Invalid method signature supplied
但是,当我对我认为查询应该包含 JS 之外的内容进行 md5 哈希时,我得到了相同的签名。我猜我一定是在字符串中包含了错误的数据,但不知道是什么。
我知道还有其他一些问题,我已经 运行 仔细检查了所有问题,以了解这里出了什么问题,但我发誓它对我来说是对的。
这是签名算法和 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
}
任何人都可以看到我在这里遗漏了什么?我完全不明白为什么这没有以请求的格式返回正确签名的 POSTable 对象 here。谢谢你的时间。
编辑:如果我没有得到任何建议,就无法感谢任何人的宝贵时间!没有人使用过 last.fm?
在调查了您的代码和其他与 last.fm
api 调用相关的帖子后,我发现 @george lee 实际上是正确的。生成 auth_sign
时无需提供 format
。
除此之外,您需要在应用 encodeURIComponent()
和 unescape()
函数后将 $.md5()
应用到 auth_sign
字符串。像这样。
hashed_sec = $.md5(unescape(encodeURIComponent(ss + last_fm_data['secret'])));
此外,在进行 ajax
调用时,您需要将 api_key, token & api_sig
作为 data
传递。但是看到你的代码,表明你正在传递 api_key, token, format, method & signature
.
因此您需要从 ajax
调用的 data
字段中删除 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
}
因此,在测试了一些回复后,我找到了解决方案。有两个问题。 编辑见下文( 第一个是需要删除
data['format'] = 'json';
正如 George Lee 指出的那样。谢谢乔治。 )
另一个问题是我错误地命名了一个变量,因此 POST 使用了错误的名称。该行
so['signature'] = hashed_sec;
应该是
so['api_sig'] = hashed_sec;
我在 Pankaj 的回答中注意到了这一点,但不幸的是他的其余回答(即包括方法)不正确。进行这两项更改解决了调用并正确签名。
感谢所有建议!
编辑: 玩了几次之后,我发现
data['format'] = 'json';
是正确的,但它没有与签名一起散列。
在散列后将 data['format'] = 'json';
添加到 POST 对象,在这种情况下将 return 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
}