API:登录
本页是MediaWiki Action API帮助文档的一部份。 |
MediaWiki API可能会要求您的应用程序或客户端提供经过身份验证的用户凭据并登录(a)查询信息或进行数据修改操作 (b)进行比请求限制较大的查询。
两种身份验证方法
有两种方法可以验证MediaWiki Action API:使用action=login或action=clientlogin。
方法1.登录 action=login
机器人和其他非交互式应用程序应使用仅所有者的OAuth使用者,因为它更安全。
如果不可用或不适用于客户端,则 login
操作可与机器人密码一起使用。
API文档
POST请求
上面的请求中的lgtoken是从API:令牌 中获取的
回应
{
"login": {
"lguserid": 21,
"result": "Success",
"lgusername": "William"
}
}
示例代码
MediaWiki JS
/*
login.js
MediaWiki API Demos
Demo of `Login` module: Sending request to login
MIT License
*/
var api = new mw.Api();
api.login( 'your_bot_username', 'your_bot_password' ).done( function ( data ) {
console.log( 'You are logged in as ' + data.login.lgusername );
} );
JavaScript
/*
edit.js
MediaWiki API Demos
Demo of `Login` module: Sending post request to login
MIT license
*/
var request = require( 'request' ).defaults( { jar: true } ),
url = 'https://test.wikipedia.org/w/api.php';
// Step 1: GET request to fetch login token
function getLoginToken() {
var params = {
action: 'query',
meta: 'tokens',
type: 'login',
format: 'json'
};
request.get( { url: url, qs: params }, function ( error, res, body ) {
var data;
if ( error ) {
return;
}
data = JSON.parse( body );
loginRequest( data.query.tokens.logintoken );
} );
}
// Step 2: POST request to log in.
// Use of main account for login is not
// supported. Obtain credentials via Special:BotPasswords
// (https://www.mediawiki.org/wiki/Special:BotPasswords) for lgname & lgpassword
function loginRequest( loginToken ) {
var params = {
action: 'login',
lgname: 'bot_username',
lgpassword: 'bot_password',
lgtoken: loginToken,
format: 'json'
};
request.post( { url: url, form: params }, function ( error, res, body ) {
if ( error ) {
return;
}
console.log( body );
} );
}
// Start From Step 1
getLoginToken();
PHP
<?php
/*
login.php
MediaWiki API Demos
Demo of `Login` module: Sending post request to login
MIT license
*/
$endPoint = "https://test.wikipedia.org/w/api.php";
$login_Token = getLoginToken(); // Step 1
loginRequest( $login_Token ); // Step 2
// Step 1: GET request to fetch login token
function getLoginToken() {
global $endPoint;
$params1 = [
"action" => "query",
"meta" => "tokens",
"type" => "login",
"format" => "json"
];
$url = $endPoint . "?" . http_build_query( $params1 );
$ch = curl_init( $url );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_COOKIEJAR, "/tmp/cookie.txt" );
curl_setopt( $ch, CURLOPT_COOKIEFILE, "/tmp/cookie.txt" );
$output = curl_exec( $ch );
curl_close( $ch );
$result = json_decode( $output, true );
return $result["query"]["tokens"]["logintoken"];
}
// Step 2: POST request to log in. Use of main account for login is not
// supported. Obtain credentials via Special:BotPasswords
// (https://www.mediawiki.org/wiki/Special:BotPasswords) for lgname & lgpassword
function loginRequest( $logintoken ) {
global $endPoint;
$params2 = [
"action" => "login",
"lgname" => "your_bot_username",
"lgpassword" => "your_bot_password",
"lgtoken" => $logintoken,
"format" => "json"
];
$ch = curl_init();
curl_setopt( $ch, CURLOPT_URL, $endPoint );
curl_setopt( $ch, CURLOPT_POST, true );
curl_setopt( $ch, CURLOPT_POSTFIELDS, http_build_query( $params2 ) );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_COOKIEJAR, "/tmp/cookie.txt" );
curl_setopt( $ch, CURLOPT_COOKIEFILE, "/tmp/cookie.txt" );
$output = curl_exec( $ch );
curl_close( $ch );
echo( $output );
}
Python
#!/usr/bin/python3
"""
login.py
MediaWiki API Demos
Demo of `Login` module: Sending post request to login
MIT license
"""
import requests
USERNAME = "your_bot_username"
PASSWORD = "your_bot_password"
S = requests.Session()
URL = "https://www.mediawiki.org/w/api.php"
# Retrieve login token first
PARAMS_0 = {
'action':"query",
'meta':"tokens",
'type':"login",
'format':"json"
}
R = S.get(url=URL, params=PARAMS_0)
DATA = R.json()
LOGIN_TOKEN = DATA['query']['tokens']['logintoken']
print(LOGIN_TOKEN)
# Send a post request to login. Using the main account for login is not
# supported. Obtain credentials via Special:BotPasswords
# (https://www.mediawiki.org/wiki/Special:BotPasswords) for lgname & lgpassword
PARAMS_1 = {
'action': "login",
'lgname': USERNAME,
'lgpassword': PASSWORD,
'lgtoken': LOGIN_TOKEN,
'format': "json"
}
R = S.post(URL, data=PARAMS_1)
DATA = R.json()
print(DATA)
assert DATA['login']['result'] == 'Success'
从MediaWiki1.27开始,使用主帐户登录不不再受支持。 通过Special:BotPasswords获得凭证或使用
clientlogin
方法。 登录并保持登录状态需要客户端对所有请求进行正确的HTTP cookie处理。 在上面的Python示例中,我们显示了会话对象requests.Session()
如何帮助cookie持久化。
可能的错误
代码 | 信息 |
---|---|
Failed | 输入了错误的用户名或密码。请再试一遍。 |
Failed | 无法继续登录。您的会话很可能超时。(或者您没有正确处理 cookie)。 |
WrongToken | 提供的令牌无效 |
NeedToken | 未提供`lgtoken` |
Aborted | 使用主帐户密码而不是机器人密码登录 |
mustpostparams | 以下参数在查询字符串中被找到,但必须在POST正文中:$1。 |
方法2. action=clientlogin
交互应用程序,例如在完全替换对基于网页的用户界面的取数而无意完全替换网站或应用程序的自定义编辑器或巡逻应用程序应使用clientlogin
操作。
但是,如果可以使用OAuth 来对工具进行身份验证,则应该使用OAuth ,因为它更简单,更安全。
该模块在MediaWiki 1.27版本开始可用。
API文档
示例21:无特殊身份验证扩展的维基程序
POST请求
api.php? action=clientlogin& loginreturnurl=http://example.com/& logintoken=29590a3037d325be70b93fb8258ed29257448cfb%2B%5C& username=William& password=secret [在Api沙盒中尝试]
通过API:令牌 在上述请求中获得令牌登录。
回应
{
"clientlogin":{
"status":"PASS",
"username":"William"
}
}
示例代码
clientlogin.py |
---|
#!/usr/bin/python3
"""
clientlogin.py
MediaWiki Action API Code Samples
Demo of `clientlogin` module: Sending post request to login
This demo app uses Flask (a Python web development framework).
MIT license
"""
import requests
from flask import Flask, render_template, flash, request
S = requests.Session()
URL = "https://en.wikipedia.org/w/api.php"
# App config.
DEBUG = True
APP = Flask(__name__)
APP.config.from_object(__name__)
APP.config['SECRET_KEY'] = 'enter_your_secret_key'
@APP.route("/", methods=['GET', 'POST'])
def show_form():
""" Render form template and handle form submission request """
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
start_client_login(username, password)
return render_template('clientlogin_form.html')
def start_client_login(username, password):
""" Send a post request along with login token, user information
and return URL to the API to log in on a wiki """
login_token = fetch_login_token()
response = S.post(url=URL, data={
'action': "clientlogin",
'username': username,
'password': password,
'loginreturnurl': 'http://127.0.0.1:5000/',
'logintoken': login_token,
'format': "json"
})
data = response.json()
if data['clientlogin']['status'] == 'PASS':
flash('Login success! Welcome, ' + data['clientlogin']['username'] + '!')
else:
flash('Oops! Something went wrong -- ' + data['clientlogin']['messagecode'])
def fetch_login_token():
""" Fetch login token via `tokens` module """
response = S.get(
url=URL,
params={
'action': "query",
'meta': "tokens",
'type': "login",
'format': "json"})
data = response.json()
return data['query']['tokens']['logintoken']
if __name__ == "__main__":
APP.run()
|
form.html |
---|
<!DOCTYPE html>
<title>MediaWiki Log in</title>
<link rel="stylesheet" href="static/bootstrap/css/bootstrap.min.css">
<div class="container">
<h2>MediaWiki Log in</h2>
<form action="" method="post" role="form">
<div class="form-group">
<div class="form-field">
<div class="label-field">Username</div>
<input name="username">
</div>
<div class="form-field">
<div class="label-field">Password</div>
<input type="password" name="password">
</div>
</div>
<button type="submit" class="btn btn-success">Log in</button>
</form>
<br>
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for message in messages %}
<div class="alert alert-info">
{{ message[1] }}
</div>
{% endfor %}
{% endif %}
{% endwith %}
</div>
<br>
</div>
</div>
|
示例22:具有特殊认证扩展功能的维基程序
具有特殊身份验证扩展, 例如ConfirmEdit (验证码),OpenID Connect ,OATHAuth (两步验证)的维基可能具有更复杂的身份验证过程。 如果在这种情况下还需要特定的字段,其描述可以从API:Authmanagerinfo 查询中获取。
步骤1:回答验证码并选择OpenID身份验证
本文档仅为示例,并不反映当前可用的任何特定OpenID扩展的行为。
客户端将用户的浏览器重定向到提供的
redirecttarget
。 OpenID程序将进行身份验证,然后重定向到维基上的 Special:OpenIDConnectReturn,这将验证OpenID响应,然后重定向到在API的第一个POST里所提供的 loginreturnurl
并添加 code
和 state
参数。 客户端此时重新获得对流程的控制权,并发出下一个API请求。回应 |
---|
{
"clientlogin": {
"status": "REDIRECT",
"redirecttarget": "https://openid.example.net/openid-auth.php?scope=openid&response_type=code&client_id=ABC&redirect_uri=https://wiki.example.org/wiki/Special:OpenIDConnectReturn&state=XYZ123",
"requests": [
{
"id": "OpenIdConnectResponseAuthenticationRequest",
"metadata": {},
"required": "required",
"provider": "OpenID Connect at example.net",
"account": "",
"fields": {
"code": {
"type": "string",
"label": "OpenID Code",
"help": "OpenID Connect code response"
},
"state": {
"type": "string",
"label": "OpenID State",
"help": "OpenID Connect state response"
},
}
}
]
}
}
|
步骤2:从OpenID返回
现在,客户端需要让用户检查两步验证应用程序中的当前代码,然后将其提交回服务器以继续身份验证过程。
回应 |
---|
{
"clientlogin": {
"status": "UI",
"message": "Two-factor authentication",
"requests": [
{
"id": "TwoFactorAuthenticationRequest",
"metadata": {},
"required": "required",
"provider": "",
"account": "",
"fields": {
"code": {
"type": "string",
"label": "Code",
"help": "Two-factor authentication code"
}
}
}
]
}
}
|
步骤3:两步验证
在某些情况下,可能会收到
RESTART
响应,例如,如果OpenID Connect扩展名没有将OpenID帐户映射到任何本地用户的信息。 在这种情况下,客户端可能会重新尝试登录,或者可能会切换到创建账户流程,在这两种情况下,都会传递loginpreservestate
或createpreservestate
参数以保留某些状态。回应 |
---|
{
"clientlogin": {
"status": "PASS",
"username": "Alice"
}
}
|
附加提醒
- 在允许匿名编辑的wiki上,不登录就可以编辑;但我们强烈推荐您先登录。 在非开放wiki上,使用任何API功能都需要登录。
- 建议为您的应用程序创建一个单独的用户帐户。 如果应用程序正在执行自动编辑或调用大型查询或高性能查询,这将尤为重要。 这样就可以轻松跟踪应用程序所做的更改,并将特殊权限应用于应用程序的账户。
- 如果发送的请求应由登录用户发出,请在发送的请求中添加
assert=user
参数,以检查用户是否已登录。 如果用户未登录,将返回assertuserfailed
错误代码。 详情请见API:声明 。 - 要检查帐户是否具有机器人权限,请在请求中添加
assert=bot
参数。 如果该帐户没有机器人权限,则将返回assertbotfailed
错误代码。 详情请见API:声明 。
參見
- API:退出
- API:用户信息 - 返回有关当前登录用户的信息
- 在mwapi中使用action=clientlogin进行交互式登录