Jump to content

API:登录

From mediawiki.org
This page is a translated version of the page API:Login and the translation is 100% complete.

MediaWiki API可能会要求您的应用程序或客户端提供经过身份验证的用户凭据并登录(a)查询信息或进行数据修改操作 (b)进行比请求限制较大的查询。

两种身份验证方法

有两种方法可以验证MediaWiki Action API:使用action=login或action=clientlogin。

方法1.登录 action=login

机器人和其他非交互式应用程序应使用仅所有者的OAuth使用者,因为它更安全。 如果不可用或不适用于客户端,则 login 操作可与机器人密码一起使用。

API文档

action=login (lg)

(main | login)
  • This module requires write rights.
  • This module only accepts POST requests.
  • Source: MediaWiki
  • License: GPL-2.0-or-later

Log in and get authentication cookies.

This action should only be used in combination with Special:BotPasswords; use for main-account login is deprecated and may fail without warning. To safely log in to the main account, use action=clientlogin.

Specific parameters:
Other general parameters are available.
lgname

Username.

lgpassword

Password.

lgdomain

Domain (optional).

lgtoken

A "login" token retrieved from action=query&meta=tokens


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文档

action=clientlogin (login)

(main | clientlogin)
  • This module requires write rights.
  • This module only accepts POST requests.
  • Source: MediaWiki
  • License: GPL-2.0-or-later

Log in to the wiki using the interactive flow.

The general procedure to use this module is:

  1. Fetch the fields available from action=query&meta=authmanagerinfo with amirequestsfor=login, and a login token from action=query&meta=tokens.
  2. Present the fields to the user, and obtain their submission.
  3. Post to this module, supplying loginreturnurl and any relevant fields.
  4. Check the status in the response.
    • If you received PASS or FAIL, you're done. The operation either succeeded or it didn't.
    • If you received UI, present the new fields to the user and obtain their submission. Then post to this module with logincontinue and the relevant fields set, and repeat step 4.
    • If you received REDIRECT, direct the user to the redirecttarget and wait for the return to loginreturnurl. Then post to this module with logincontinue and any fields passed to the return URL, and repeat step 4.
    • If you received RESTART, that means the authentication worked but we don't have a linked user account. You might treat this as UI or as FAIL.
Specific parameters:
Other general parameters are available.
loginrequests

Only use these authentication requests, by the id returned from action=query&meta=authmanagerinfo with amirequestsfor=login or from a previous response from this module.

Separate values with | or alternative.
Maximum number of values is 50 (500 for clients that are allowed higher limits).
loginmessageformat

Format to use for returning messages.

One of the following values: html, none, raw, wikitext
Default: wikitext
loginmergerequestfields

Merge field information for all authentication requests into one array.

Type: boolean (details)
loginpreservestate

Preserve state from a previous failed login attempt, if possible.

Type: boolean (details)
loginreturnurl

Return URL for third-party authentication flows, must be absolute. Either this or logincontinue is required.

Upon receiving a REDIRECT response, you will typically open a browser or web view to the specified redirecttarget URL for a third-party authentication flow. When that completes, the third party will send the browser or web view to this URL. You should extract any query or POST parameters from the URL and pass them as a logincontinue request to this API module.

logincontinue

This request is a continuation after an earlier UI or REDIRECT response. Either this or loginreturnurl is required.

Type: boolean (details)
logintoken

A "login" token retrieved from action=query&meta=tokens

This parameter is required.
*
This module accepts additional parameters depending on the available authentication requests. Use action=query&meta=authmanagerinfo with amirequestsfor=login (or a previous response from this module, if applicable) to determine the requests available and the fields that they use.
Examples:
Start the process of logging in to the wiki as user Example with password ExamplePassword.
api.php?action=clientlogin&username=Example&password=ExamplePassword&loginreturnurl=http://example.org/&logintoken=123ABC [open in sandbox]
Continue logging in after a UI response for two-factor auth, supplying an OATHToken of 987654.
api.php?action=clientlogin&logincontinue=1&OATHToken=987654&logintoken=123ABC [open in sandbox]


示例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 查询中获取。

客户端将用户的浏览器重定向到提供的 redirecttarget。 OpenID程序将进行身份验证,然后重定向到维基上的 Special:OpenIDConnectReturn,这将验证OpenID响应,然后重定向到在API的第一个POST里所提供的 loginreturnurl 并添加 codestate 参数。 客户端此时重新获得对流程的控制权,并发出下一个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"
                    },
                }
            }
        ]
    }
}
现在,客户端需要让用户检查两步验证应用程序中的当前代码,然后将其提交回服务器以继续身份验证过程。
回应
{
    "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"
                    }
                }
            }
        ]
    }
}
在某些情况下,可能会收到 RESTART 响应,例如,如果OpenID Connect扩展名没有将OpenID帐户映射到任何本地用户的信息。 在这种情况下,客户端可能会重新尝试登录,或者可能会切换到创建账户流程,在这两种情况下,都会传递loginpreservestatecreatepreservestate参数以保留某些状态。
回应
{
    "clientlogin": {
        "status": "PASS",
        "username": "Alice"
    }
}

附加提醒

  • 在允许匿名编辑的wiki上,不登录就可以编辑;但我们强烈推荐您先登录。 在非开放wiki上,使用任何API功能都需要登录。
  • 建议为您的应用程序创建一个单独的用户帐户。 如果应用程序正在执行自动编辑或调用大型查询或高性能查询,这将尤为重要。 这样就可以轻松跟踪应用程序所做的更改,并将特殊权限应用于应用程序的账户。
  • 如果发送的请求应由登录用户发出,请在发送的请求中添加assert=user参数,以检查用户是否已登录。 如果用户未登录,将返回assertuserfailed错误代码。 详情请见API:声明
  • 要检查帐户是否具有机器人权限,请在请求中添加assert=bot参数。 如果该帐户没有机器人权限,则将返回assertbotfailed错误代码。 详情请见API:声明

參見