如何在 Node.js 中登录 MediaWiki(维基百科)API
How to Login to MediaWiki (Wikipedia) API in Node.js
我正在尝试 API:Login 文档中描述的 Wikipedia 客户端登录流程,但出现错误:
1) 我通过 HTTP GET https://en.wikipedia.org/w/api.php?action=query&meta=tokens&type=login&format=json
正确地获得了一个令牌
我得到一个有效的 logintoken
字符串。
2.1) 然后我尝试 clientlogin
像:
HTTP POST /w/api.php?action=clientlogin&format=json&lgname=xxxx&lgtoken=xxxx%2B%5C
而 POST BODY 是
{
"lgpassword" : "xxxxx",
"lgtoken" : "xxxxx"
}
但是我得到一个错误:
{
"error": {
"code": "notoken",
"info": "The \"token\" parameter must be set."
},
"servedby": "mw1228"
}
如果我尝试将 lgtoken
更改为 token
,我会得到相同的结果。
2.2) 然后我尝试了旧方法,即 action=login
并传递 body,但它不起作用,因为它返回另一个登录令牌:HTTP POST https://en.wikipedia.org/w/api.php?action=login&format=json&lgname=xxxx
和相同的POSTBODY
然后我得到
{
"warnings": {}
},
"login": {
"result": "NeedToken",
"token": "xxxxx+\"
}
文档 here 指出
NeedToken if the lgtoken parameter was not provided or no session was active (e.g. your cookie handling is broken).
但我已经通过 json body 中的 lgtoken
,如图所示。
我正在使用 Node.js 和 built-in http
模块,它应该通过并保持 session Cookies
以正确的方式(与其他 api 一起工作正常)。
我在 LrMediaWiki 客户端上发现了类似的问题 here。
[更新]
这是我当前的实现:
Wikipedia.prototype.loginUser = function (username, password) {
var self = this;
return new Promise((resolve, reject) => {
var cookies = self.cookies({});
var headers = {
'Cookie': cookies.join(';'),
'Accept': '*/*',
'User-Agent': self.browser.userAgent()
};
// fetch login token
self.api.RequestGetP('/w/api.php', headers, {
action: 'query',
meta: 'tokens',
type: 'login',
format: 'json'
})
.then(response => { // success
if (response.query && response.query.tokens && response.query.tokens['logintoken']) {
self.login.logintoken = response.query.tokens['logintoken'];
self.logger.info("Wikipedia.login token:%s", self.login);
return self.api.RequestPostP('/w/api.php', headers, {
action: 'login',
format: 'json',
lgname: username
},
{
lgpassword: password,
lgtoken: self.login.logintoken
});
} else {
var error = new Error('no logintoken');
return reject(error);
}
})
.then(response => { // success
return resolve(response);
})
.catch(error => { // error
self.logger.error("Wikipedia.login error%s\n%@", error.message, error.stack);
return reject(error);
});
});
}//loginUser
其中 this.api
是 Node.js http 的简单包装器,源代码可用 here 并且 api 签名如下:
Promise:API.RequestGetP(url,headers,querystring)
Promise:API.RequestPostP(url,headers,querystring,body)
我认为你所说的lgtoken
和lgname
在你正在使用的URL中,然后lgpassword
和 lgtoken
(再次!)在 JSON-encoded POST body.
这不是 Mediawiki API 的工作方式。
您提交全部作为POST参数。 JSON 永远不会涉及,除非您要求结果以该格式返回。我无法帮助您修复代码,因为您没有提供代码,但这是您需要做的。 (如果你用你的代码编辑你的问题,我会尽力帮助你。)
看到你的代码后,我会假设(不知道你的代码的细节)你想要这样的东西:
return self.api.RequestPostP('/w/api.php', headers, {
action: 'login',
format: 'json',
lgname: username,
lgpassword: password,
lgtoken: self.login.logintoken
});
如果当前接受的答案对某人不起作用,则以下方法肯定会起作用。我已经使用 axios 库发送请求。可以使用任何库,但关键在于正确格式化 body 和 headers。
let url = "https://test.wikipedia.org/w/api.php";
let params = {
action: "query",
meta: "tokens",
type: "login",
format: "json"
};
axios.get(url, { params: params }).then(resp => {
let loginToken = resp.data.query.tokens.logintoken
let cookie = resp.headers["set-cookie"].join(';');
let body = {
action: 'login',
lgname: 'user_name',
lgpassword: 'password',
lgtoken: loginToken,
format: 'json'
}
let bodyData = new URLSearchParams(body).toString();
axios.post(url, bodyData, {
headers: {
Cookie: cookie,
}
}).then(resp => {
// You're now logged in!
// You'll have to add the following cookie in the headers again for any further requests that you might make
let cookie = resp.headers["set-cookie"].join(';')
console.log(resp.data)
})
})
你应该会看到这样的回复
{
login: { result: 'Success', lguserid: 0000000, lgusername: 'Username' }
}
第二个 post 请求让我卡住了几个小时,试图找出问题所在。您需要使用 URLSearchParams 之类的 API 以编码形式发送数据,或者您自己手动输入 body 作为字符串。
我正在尝试 API:Login 文档中描述的 Wikipedia 客户端登录流程,但出现错误:
1) 我通过 HTTP GET https://en.wikipedia.org/w/api.php?action=query&meta=tokens&type=login&format=json
我得到一个有效的 logintoken
字符串。
2.1) 然后我尝试 clientlogin
像:
HTTP POST /w/api.php?action=clientlogin&format=json&lgname=xxxx&lgtoken=xxxx%2B%5C
而 POST BODY 是
{
"lgpassword" : "xxxxx",
"lgtoken" : "xxxxx"
}
但是我得到一个错误:
{
"error": {
"code": "notoken",
"info": "The \"token\" parameter must be set."
},
"servedby": "mw1228"
}
如果我尝试将 lgtoken
更改为 token
,我会得到相同的结果。
2.2) 然后我尝试了旧方法,即 action=login
并传递 body,但它不起作用,因为它返回另一个登录令牌:HTTP POST https://en.wikipedia.org/w/api.php?action=login&format=json&lgname=xxxx
和相同的POSTBODY
然后我得到
{
"warnings": {}
},
"login": {
"result": "NeedToken",
"token": "xxxxx+\"
}
文档 here 指出
NeedToken if the lgtoken parameter was not provided or no session was active (e.g. your cookie handling is broken).
但我已经通过 json body 中的 lgtoken
,如图所示。
我正在使用 Node.js 和 built-in http
模块,它应该通过并保持 session Cookies
以正确的方式(与其他 api 一起工作正常)。
我在 LrMediaWiki 客户端上发现了类似的问题 here。
[更新] 这是我当前的实现:
Wikipedia.prototype.loginUser = function (username, password) {
var self = this;
return new Promise((resolve, reject) => {
var cookies = self.cookies({});
var headers = {
'Cookie': cookies.join(';'),
'Accept': '*/*',
'User-Agent': self.browser.userAgent()
};
// fetch login token
self.api.RequestGetP('/w/api.php', headers, {
action: 'query',
meta: 'tokens',
type: 'login',
format: 'json'
})
.then(response => { // success
if (response.query && response.query.tokens && response.query.tokens['logintoken']) {
self.login.logintoken = response.query.tokens['logintoken'];
self.logger.info("Wikipedia.login token:%s", self.login);
return self.api.RequestPostP('/w/api.php', headers, {
action: 'login',
format: 'json',
lgname: username
},
{
lgpassword: password,
lgtoken: self.login.logintoken
});
} else {
var error = new Error('no logintoken');
return reject(error);
}
})
.then(response => { // success
return resolve(response);
})
.catch(error => { // error
self.logger.error("Wikipedia.login error%s\n%@", error.message, error.stack);
return reject(error);
});
});
}//loginUser
其中 this.api
是 Node.js http 的简单包装器,源代码可用 here 并且 api 签名如下:
Promise:API.RequestGetP(url,headers,querystring)
Promise:API.RequestPostP(url,headers,querystring,body)
我认为你所说的lgtoken
和lgname
在你正在使用的URL中,然后lgpassword
和 lgtoken
(再次!)在 JSON-encoded POST body.
这不是 Mediawiki API 的工作方式。
您提交全部作为POST参数。 JSON 永远不会涉及,除非您要求结果以该格式返回。我无法帮助您修复代码,因为您没有提供代码,但这是您需要做的。 (如果你用你的代码编辑你的问题,我会尽力帮助你。)
看到你的代码后,我会假设(不知道你的代码的细节)你想要这样的东西:
return self.api.RequestPostP('/w/api.php', headers, {
action: 'login',
format: 'json',
lgname: username,
lgpassword: password,
lgtoken: self.login.logintoken
});
如果当前接受的答案对某人不起作用,则以下方法肯定会起作用。我已经使用 axios 库发送请求。可以使用任何库,但关键在于正确格式化 body 和 headers。
let url = "https://test.wikipedia.org/w/api.php";
let params = {
action: "query",
meta: "tokens",
type: "login",
format: "json"
};
axios.get(url, { params: params }).then(resp => {
let loginToken = resp.data.query.tokens.logintoken
let cookie = resp.headers["set-cookie"].join(';');
let body = {
action: 'login',
lgname: 'user_name',
lgpassword: 'password',
lgtoken: loginToken,
format: 'json'
}
let bodyData = new URLSearchParams(body).toString();
axios.post(url, bodyData, {
headers: {
Cookie: cookie,
}
}).then(resp => {
// You're now logged in!
// You'll have to add the following cookie in the headers again for any further requests that you might make
let cookie = resp.headers["set-cookie"].join(';')
console.log(resp.data)
})
})
你应该会看到这样的回复
{
login: { result: 'Success', lguserid: 0000000, lgusername: 'Username' }
}
第二个 post 请求让我卡住了几个小时,试图找出问题所在。您需要使用 URLSearchParams 之类的 API 以编码形式发送数据,或者您自己手动输入 body 作为字符串。