Как войти в API MediaWiki (Wikipedia) в Node.js
Я пытаюсь описать процесс входа клиента из Википедии в API: Документация для входа, но что-то не так:
1) я правильно получаю токен с HTTP GEThttps://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
и ПОЧТА ТЕЛА была
{
"lgpassword" : "xxxxx",
"lgtoken" : "xxxxx"
}
Но я получаю ошибку:
{
"error": {
"code": "notoken",
"info": "The \"token\" parameter must be set."
},
"servedby": "mw1228"
}
Если я попытаюсь изменитьlgtoken
вtoken
Я получаю тот же результат.
2.2) Затем я попробовал старый метод, т.е.action=login
и передает тело, но оно не работает, так как возвращает мне еще один токен входа в систему: HTTP POSThttps://en.wikipedia.org/w/api.php?action=login&format=json&lgname=xxxx
и тот же почтовый орган
Я тогда получаю
{
"warnings": {}
},
"login": {
"result": "NeedToken",
"token": "xxxxx+\\"
}
где документы утверждают, что
NeedToken if the lgtoken parameter was not provided or no session was active (e.g. your cookie handling is broken).
но я прошел lgtoken
в теле JSON, как показано. Я использую Node.js и встроенный http
модуль, который должен пройти и сохранить сессию Cookies
в правильном направлении (с другими API это работает нормально).
Я нашел похожую проблему на клиенте LrMediaWiki здесь.
[ОБНОВЛЕНИЕ] Это моя текущая реализация:
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, исходный код доступен здесь, а подписи API выглядят так:
Promise:API.RequestGetP(url,headers,querystring)
Promise:API.RequestPostP(url,headers,querystring,body)
2 ответа
Если принятый в настоящее время ответ у кого-то не работает, следующий метод определенно сработает. Я использовал библиотеку axios для отправки запросов. Можно использовать любую библиотеку, но ключ кроется в правильном форматировании тела и заголовков.
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' }
}
Второй почтовый запрос был там, где я застрял на несколько часов, пытаясь понять, что не так. Вам необходимо отправить данные в закодированной форме с помощью API, такого как URLSearchParams, или просто вручную набрав текст в виде строки.
Я думаю, из того, что вы говорите, у вас есть lgtoken
а также lgname
в URL-адресе, который вы используете, а затем lgpassword
а также lgtoken
(снова!) в теле POST в JSON-кодировке.
Это не то, как работает Mediawiki API.
Вы отправляете все это как параметры POST. JSON никогда не участвует, за исключением случаев, когда вы запрашиваете возвращение результата в этом формате. Я не могу помочь вам исправить ваш код, поскольку вы его не предоставляете, но это то, что вам нужно сделать. (Если вы измените свой вопрос с помощью своего кода, я сделаю все возможное, чтобы помочь вам.)
После просмотра вашего кода я предположу (не зная деталей вашего кода), что вы хотите что-то вроде этого:
return self.api.RequestPostP('/w/api.php', headers, {
action: 'login',
format: 'json',
lgname: username,
lgpassword: password,
lgtoken: self.login.logintoken
});