API:로그인

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

다음과 같은 경우 미디어위키 API는 프로그램이나 사용자가 API를 사용하는 데 있어 인증된 사용자 권한과 로그인을 필요로 합니다.

  1. 쿼리문을 작성하여 정보를 불러오거나 수정을 해야할 때
  2. 요청 제한량을 완화하고 더 많은 쿼리문을 사용해야할 때

인증을 위한 두가지 방법

미디어위키 Action API 사용을 위한 인증 방법으로는 action=login과 action=clientlogin가 있습니다.

첫 번째 방법, action=login

봇이나 여타 즉각적인 서버와의 응답을 요하지 않는 프로그램들은 보안을 위해 OAuth를 사용하는 것이 좋습니다. 만약 사용할 수 없을 경우에는 봇 비밀번호를 따로 만들어서 사용할 수 있습니다.

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:Tokens 를 참고하세요.

응답

{  
   "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'
미디어위키 1.27 이후 버전부터 로그인을 위해 메인 계정을 사용하는 것은 지원되지 않습니다. Special:BotPasswords의 새로운 봇 비밀번호 만들기나 clientlogin를 통해 권한을 얻으세요. 로그인이나 로그인 상태 유지는 항상 HTTP 쿠키를 올바르게 다뤄야 가능합니다. 위의 파이썬 예제에서 requests.Session()이 어떻게 쿠키를 유지하는지 알 수 있습니다.

발생가능한 오류

코드 정보
Failed 아이디나 비밀번호가 정확하지 않은 경우.
Failed 세션이 종료되어 로그인을 진행할 수 없음. 또는 쿠키를 잘못된 방식으로 취급했을 경우.
WrongToken 입력한 토큰이 유효하지 않을 경우.
NeedToken 토큰을 입력하지 않았을 경우.
Aborted 봇 비밀번호가 아닌 주계정 비밀번호로 로그인했을 경우.
mustpostparams The following parameters were found in the query string, but must be in the POST body: $1.

두 번째 방법, action=clientlogin

커스텀 편집기나 관리 프로그램 등 완전히 내용을 교체하는 방식이 아닌 즉각적인 응답을 필요로 하는 프로그램이나 웹 기반의 편집을 대체하기 위한 핸드폰 어플의 경우 clientlogin의 방식을 사용하는 것이 좋습니다. 하지만 인증 도구를 사용하는 것이 더 간편하고 안전하다면 OAuth 방식을 우선적으로 사용하는 것이 좋습니다. 미디어 위키 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:Tokens 에서 설명하고 있습니다.

응답

{  
   "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 응답을 검증합니다. codestate 매개변수를 추가한 쿼리문에 이전 게재 요청(POST)에서 먼저 입력했던 loginreturnurl의 주소로 리다이렉트합니다. 사용자는 이를 통해 권한을 얻어 다음 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"
                    }
                }
            }
        ]
    }
}
예를들어 OpenID의 연결 확장 기능이 OpenID 계정의 어떤 로컬 사용자와도 연결이 없을 경우 RESTART라는 응답을 받을 수 있습니다. 이때 사용자는 로그인 절차를 다시 진행하거나 계정을 생성해야 할 수도 있습니다. 이럴 경우 loginpreservestatecreatepreservestate의 매개변수를 제공해야 합니다.
응답
{
    "clientlogin": {
        "status": "PASS",
        "username": "Alice"
    }
}

추가 참고사항

  • 아이피 사용자로 편집이 가능한 위키의 경우 로그인을 하지 않고 API를 이용할 수 있지만, 로그인을 권장합니다. 개인의 사설 위키에서 로그인할 경우 모든 API 기능을 사용할 수 있습니다.
  • 프로그램 구동을 위해 별도의 사용자 계정을 생성하는 것이 좋습니다. 이는 프로그램이 자동 편집을 수행하거나 서버에 높은 부담을 요하는 질의들을 실행하는 경우 특히 중요합니다. 따라서 프로그램에서 변경된 내용을 추적하고 프로그램을 사용하는 계정에 특별한 권한을 적용하는 것이 용이합니다.
  • 로그인 사용자가 직접 요청을 전송 해야하는 경우, 사용자가 로그인했는지 여부를 확인하기 위해 전송하는 요청에 assert=user 매개 변수를 추가하십시오. 사용자가 로그인하지 않은 경우, assertuserfailed라는 오류 코드가 반환됩니다. 자세한 사항은 API:표명 을 참고하십시오.
  • 계정이 봇 권한을 가지고 있는지 확인하려면 요청에 매개 변수 assert=bot을 추가하세요. 계정에 봇 권한이 없다면 오류 코드 assertbotfailed가 반환됩니다. 자세한 사항은 API:표명 을 참고하십시오.

같이 보기