API:로그인
이 문서는 MediaWiki Action API 문서의 부분입니다. |
다음과 같은 경우 미디어위키 API는 프로그램이나 사용자가 API를 사용하는 데 있어 인증된 사용자 권한과 로그인을 필요로 합니다.
- 쿼리문을 작성하여 정보를 불러오거나 수정을 해야할 때
- 요청 제한량을 완화하고 더 많은 쿼리문을 사용해야할 때
인증을 위한 두가지 방법
미디어위키 Action API 사용을 위한 인증 방법으로는 action=login과 action=clientlogin가 있습니다.
첫 번째 방법, action=login
봇이나 여타 즉각적인 서버와의 응답을 요하지 않는 프로그램들은 보안을 위해 OAuth를 사용하는 것이 좋습니다. 만약 사용할 수 없을 경우에는 봇 비밀번호를 따로 만들어서 사용할 수 있습니다.
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'
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 설명문서
예제 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 응답을 검증합니다. code
및 state
매개변수를 추가한 쿼리문에 이전 게재 요청(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"
},
}
}
]
}
}
|
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
라는 응답을 받을 수 있습니다. 이때 사용자는 로그인 절차를 다시 진행하거나 계정을 생성해야 할 수도 있습니다. 이럴 경우 loginpreservestate
과 createpreservestate
의 매개변수를 제공해야 합니다.응답 |
---|
{
"clientlogin": {
"status": "PASS",
"username": "Alice"
}
}
|
추가 참고사항
- 아이피 사용자로 편집이 가능한 위키의 경우 로그인을 하지 않고 API를 이용할 수 있지만, 로그인을 권장합니다. 개인의 사설 위키에서 로그인할 경우 모든 API 기능을 사용할 수 있습니다.
- 프로그램 구동을 위해 별도의 사용자 계정을 생성하는 것이 좋습니다. 이는 프로그램이 자동 편집을 수행하거나 서버에 높은 부담을 요하는 질의들을 실행하는 경우 특히 중요합니다. 따라서 프로그램에서 변경된 내용을 추적하고 프로그램을 사용하는 계정에 특별한 권한을 적용하는 것이 용이합니다.
- 로그인 사용자가 직접 요청을 전송 해야하는 경우, 사용자가 로그인했는지 여부를 확인하기 위해 전송하는 요청에
assert=user
매개 변수를 추가하십시오. 사용자가 로그인하지 않은 경우,assertuserfailed
라는 오류 코드가 반환됩니다. 자세한 사항은 API:표명 을 참고하십시오. - 계정이 봇 권한을 가지고 있는지 확인하려면 요청에 매개 변수
assert=bot
을 추가하세요. 계정에 봇 권한이 없다면 오류 코드assertbotfailed
가 반환됩니다. 자세한 사항은 API:표명 을 참고하십시오.
같이 보기
- API:로그아웃
- API:Userinfo - 현재 로그인한 사용자에 대한 정보를 보여줍니다.
- 미디어위키 API에서 빠른 응답을 제공하는 action=clientlogin.