API:登录
| 本页是MediaWiki Action API帮助文档的一部分。 |
MediaWiki API可能会要求您的应用程序或客户端提供经过身份验证的用户凭据并登录(a)查询信息或进行数据修改操作 (b)进行比请求限制较大的查询。
两种身份验证方法
有两种方法可以验证MediaWiki Action API:使用action=login或action=clientlogin。
For most modern clients and applications, action=clientlogin is recommended.
See the end-to-end clientlogin example including token retrieval and follow-up handling.
方法1.登录 action=login
机器人和其他非交互式应用程序应使用仅所有者的OAuth使用者,因为它更安全。
如果不可用或不适用于客户端,则 login 操作可与机器人密码一起使用。
API文档
示例
POST请求
回应
{
"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'
BASH
#!/usr/bin/env bash
# load config
export MW_PASS="your bot password" # from Special:BotPassword
export MW_USER="your bot name"
export MW_URL="https://www.mediawiki.org/w/" # besure slash at end
# get token
API_URL="api.php"
RESULT=$(curl -fsSL -X POST \
-d action=query \
-d meta=tokens \
-d type=login \
-d format=json \
-c cookie.txt \
-b cookie.txt \
"${MW_URL}${API_URL}")
RESULT=${RESULT/*token\":\"}
TOKEN=${RESULT%\\\"*}
# perform login
RESULT=$(curl -fsSL -X POST \
--data-urlencode action=login \
-d lgname="$MW_USER" \
-d lgpassword="$MW_PASS" \
--data-urlencode lgtoken="$TOKEN" \
-d format=json \
-c cookie.txt \
-b cookie.txt \
"${MW_URL}${API_URL}")
echo $RESULT
clientlogin方法。 登录并保持登录状态需要客户端对所有请求进行正确的HTTP cookie处理。 在上面的Python示例中,我们显示了会话对象requests.Session()如何帮助cookie持久化。
方法2. action=clientlogin
交互应用程序,例如在完全替换对基于网页的用户界面的取数而无意完全替换网站或应用程序的自定义编辑器或巡逻应用程序应使用clientlogin操作。
但是,如果可以使用OAuth来对工具进行身份验证,则应该使用OAuth,因为它更简单,更安全。
该模块在MediaWiki 1.27版本开始可用。
API文档
Example: Login using action=clientlogin (MediaWiki 1.27+)
This example demonstrates a minimal client-side login flow using action=clientlogin.
Step 1: Fetch a login token
GET https://www.mediawiki.org/w/api.php?action=query&meta=tokens&type=login&format=json
Step 2: Submit credentials using clientlogin
POST https://www.mediawiki.org/w/api.php
action=clientlogin
&username=ExampleUser
&password=ExamplePassword
&logintoken=LOGIN_TOKEN_FROM_STEP_1
&loginreturnurl=https://example.org/
&format=json
Step 3: Handle the response
If the response status is PASS, the user is logged in successfully.
If the response status is UI or CONTINUE, the client must submit additional fields as instructed in the response (e.g. CAPTCHA or two-factor authentication) and repeat the request using logincontinue.
示例21:无特殊身份验证扩展的维基程序
POST请求
通过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"
}
}
|
可能的错误
| 代码 | 信息 |
|---|---|
| Failed | 输入了错误的用户名或密码。请再试一遍。 |
| Failed | 无法继续登录。您的会话很可能超时。(或者您没有正确处理 cookie)。 |
| WrongToken | 提供的令牌无效 |
| NeedToken | 未提供`lgtoken` |
| Aborted | 使用主帐户密码而不是机器人密码登录 |
| mustpostparams | 以下参数在查询字符串中被找到,但必须在POST正文中:$1。 |
附加提醒
- 在允许匿名编辑的wiki上,不登录就可以编辑;但我们强烈推荐您先登录。 在非开放wiki上,使用任何API功能都需要登录。
- 建议为您的应用程序创建一个单独的用户帐户。 如果应用程序正在执行自动编辑或调用大型查询或高性能查询,这将尤为重要。 这样就可以轻松跟踪应用程序所做的更改,并将特殊权限应用于应用程序的账户。
- 如果发送的请求应由登录用户发出,请在发送的请求中添加
assert=user参数,以检查用户是否已登录。 如果用户未登录,将返回assertuserfailed错误代码。 详情请见API:声明。 - 要检查帐户是否具有机器人权限,请在请求中添加
assert=bot参数。 如果该帐户没有机器人权限,则将返回assertbotfailed错误代码。 详情请见API:声明。
参阅
- API:退出登录
- API:用户信息 – 返回有关当前登录用户的信息
- 在mwapi中使用action=clientlogin进行交互式登录