我正在使用MediaWiki编写自定义的PrimaryAuthenticationProvider,以针对我的API(而不是MediaWiki数据库)进行授权。但是,当我通过以下方式关闭LocalSettings.php中的自动创建功能时:
$wgGroupPermissions['*']['createaccount'] = false;
$wgGroupPermissions['*']['edit'] = false;
$wgGroupPermissions['*']['read'] = false;
当我尝试使用正确的凭据登录我的API时,请求失败,并显示错误:Auto-creation of a local account failed: Automatic account creation is not allowed.
我想我没有对应该返回MediaWiki不应该创建用户的正确值的函数之一进行存根处理,但是我找不到哪个函数。当我启用$wgGroupPermissions['*']['createaccount'] = false;
时,它开始工作,但是我想完全禁止创建帐户。我该如何实现?
这是我的身份验证提供程序的核心:
<?php
/**
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License,or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or fitness FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not,write to the Free Software Foundation,Inc.,* 51 Franklin Street,Fifth Floor,Boston,MA 02110-1301,USA.
* http://www.gnu.org/copyleft/gpl.html
*
* @file
* @ingroup Auth
*/
use \MediaWiki\Auth\AuthenticationRequest;
use \MediaWiki\Auth\ButtonAuthenticationRequest;
use \MediaWiki\Auth\AbstractPrimaryAuthenticationProvider;
use \MediaWiki\Auth\AbstractPasswordPrimaryAuthenticationProvider;
use \MediaWiki\Auth\AuthManager;
use \MediaWiki\Auth\AuthenticationResponse;
/**
* A primary authentication provider that uses the password field in the 'user' table.
* @ingroup Auth
* @since 1.27
*/
class MyAEGEEApiPrimaryAuthenticationProvider
extends AbstractPasswordPrimaryAuthenticationProvider
{
/**
* @param array $params Settings
* the local password will be invalidated when authentication is changed
* and new users will not have a valid local password set.
*/
public function __construct( $params = [] ) {
parent::__construct( $params );
$this->baseHost = 'https://my.aegee.eu';
$this->loginUrl = $this->baseHost.'/services/oms-core-elixir/api/login';
$this->getUserUrl = $this->baseHost.'/services/oms-core-elixir/api/members/me';
}
/**
* Check if the password has expired and needs a reset
*
* @param string $username
* @param \stdClass $row A row from the user table
* @return \stdClass|null
*/
protected function getPasswordResetData( $username,$row ) {
return null;
}
/**
* Makes a /login request to core.
* @param{string} $username
* @param{string} $password
* @return $access_token
*/
private function tryLogin($username,$password) {
$ch = curl_init($this->loginUrl);
$body = json_encode(array(
'username'=>$username,'password'=>$password
));
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_POSTFIELDS,$body);
curl_setopt($ch,CURLOPT_POST,CURLOPT_HTTPHEADER,array(
'accept: application/json','Content-Type: application/json'
));
$response = curl_exec($ch);
$error = curl_error($ch);
$errno = curl_errno($ch);
if (is_resource($ch)) {
curl_close($ch);
}
if (0 !== $errno) {
wfDebugLog( 'MyAEGEEApi','Auth request returned error,failing.' );
return null;
}
$response_parsed = json_decode($response);
if (!$response_parsed->success) {
wfDebugLog( 'MyAEGEEApi','Auth request not successful,failing.' );
return null;
}
return $response_parsed->access_token;
}
/**
* Fetches user from core.
* @param{string} $access_token
* @return $user
*/
private function tryGetUser($access_token) {
$ch = curl_init($this->getUserUrl);
$body = json_encode(array(
'username'=>$username,'Content-Type: application/json','X-Auth-Token: '.$access_token
));
$response = curl_exec($ch);
$error = curl_error($ch);
$errno = curl_errno($ch);
if (is_resource($ch)) {
curl_close($ch);
}
if (0 !== $errno) {
wfDebugLog( 'MyAEGEEApi','User request returned error,'User request not successful,failing.' );
return null;
}
return $response_parsed->data;
}
/**
* All fun starts here.
*/
public function beginPrimaryAuthentication( array $reqs ) {
if ( !$reqs[0] ) {
wfDebugLog( 'MyAEGEEApi','No req,failing' );
return AuthenticationResponse::newabstain();
}
$username = $reqs[0]->username;
$password = $reqs[0]->password;
if ( $username === null || $password === null ) {
wfDebugLog( 'MyAEGEEApi','Empty password or username,failing' );
return AuthenticationResponse::newabstain();
}
$username = User::getcanonicalName( $username,'usable' );
if ( $username === false ) {
wfDebugLog( 'MyAEGEEApi','username not usable,failing' );
return AuthenticationResponse::newabstain();
}
$access_token = $this->tryLogin($username,$password);
wfDebugLog( 'MyAEGEEApi','Got access token');
if (!$access_token) {
wfDebugLog( 'MyAEGEEApi','access token failed,failing.');
return AuthenticationResponse::newabstain();
}
wfDebugLog( 'MyAEGEEApi','Auth succeeded.');
$user = $this->tryGetUser($access_token);
if (!$user) {
wfDebugLog( 'MyAEGEEApi','User failed,failing.');
return AuthenticationResponse::newabstain();
}
$username = $user->first_name.' '.$user->last_name;
wfDebugLog( 'MyAEGEEApi','User succeeded: '.$username);
return AuthenticationResponse::newPass( $username );
}
public function testUserCanAuthenticate( $username ) {
wfDebugLog( 'MyAEGEEApi','testUserCanAuthenticate start');
return true;
}
public function testUserExists( $username,$flags = User::READ_NORMAL ) {
wfDebugLog( 'MyAEGEEApi','testUserExists called');
return false;
}
/**
* A stub to just implement something.
*/
public function providerAllowsAuthenticationDataChange(
AuthenticationRequest $req,$checkData = true
) {
wfDebugLog( 'MyAEGEEApi','providerAllowsAuthenticationDataChange called');
return \StatusValue::newGood( 'ignored' );
}
/**
* A stub to just implement something.
*/
public function providerChangeAuthenticationData( AuthenticationRequest $req ) {
wfDebugLog( 'MyAEGEEApi','providerChangeAuthenticationData start');
}
/**
* A stub to just implement something.
*/
public function accountCreationType() {
wfDebugLog( 'MyAEGEEApi','accountCreationType called start');
return self::TYPE_NONE;
}
/**
* A stub to just implement something.
*/
public function testForaccountCreation( $user,$creator,array $reqs ) {
wfDebugLog( 'MyAEGEEApi','testForaccountCreation called');
}
/**
* A stub to just implement something.
*/
public function beginPrimaryaccountCreation( $user,'beginPrimaryaccountCreation called');
return AuthenticationResponse::newabstain();
}
/**
* A stub to just implement something.
*/
public function finishaccountCreation( $user,AuthenticationResponse $res ) {
wfDebugLog( 'MyAEGEEApi','finishaccountCreation called');
return null;
}
}
然后在调试控制台中获得以下日志:
IP: 172.18.0.2
Start request POST /index.php/Special:UserLogin
HTTP HEADERS:
HOST: localhost
USER-AGENT: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:70.0) Gecko/20100101 Firefox/70.0
CONTENT-LENGTH: 208
accEPT: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
accEPT-ENCODING: gzip,deflate
accEPT-LANGUAGE: en-US,en;q=0.5
CONTENT-TYPE: application/x-www-form-urlencoded
COOKIE: __test=1; Webstorm-87597fa=870153af-a572-4e74-a5d9-c7709900917d; sails.sid=s%3ASAu438xerbZoNUyYmK9AIxJCEBE_KkV0.%2FEydN2aTQPEaxd%2BhxAq3dkfHy1YDlnv2joc82HyQ%2Bi8; mediawiki_session=s0i4jb61ka5ckdhnfqoids1mjb9rl520
DNT: 1
ORIGIN: http://localhost
REFERER: http://localhost/index.php/Special:UserLogin
UPGRADE-INSECURE-REQUESTS: 1
X-FORWARDED-FOR: <IP>
X-FORWARDED-HOST: localhost
X-FORWARDED-PORT: 80
X-FORWARDED-PROTO: http
X-FORWARDED-SERVER: 28ef83ab1502
X-REAL-IP: <IP>
[caches] cluster: APCUBagOStuff,WAN: mediawiki-main-default,stash: db-replicated,message: APCUBagOStuff,session: APCUBagOStuff
[caches] LocalisationCache: using store LCStoreDB
[DBConnection] Wikimedia\Rdbms\LoadBalancer::openConnection: calling initLB() before first connection.
[DBReplication] Cannot use Chronologyprotector with EmptyBagOStuff.
[DBReplication] Wikimedia\Rdbms\LBFactory::getchronologyprotector: using request info {
"IPAddress": "172.18.0.2","UserAgent": "Mozilla\/5.0 (Macintosh; Intel Mac OS X 10.15; rv:70.0) Gecko\/20100101 Firefox\/70.0","ChronologyProtection": false,"ChronologyPositionIndex": 0,"ChronologyClientId": null
}
[DBConnection] Wikimedia\Rdbms\LoadBalancer::openLocalConnection: connected to database 0 at 'maria-mediawiki'.
[session] Session "s0i4jb61ka5ckdhnfqoids1mjb9rl520" requested without UserID cookie
[MessageCache] MessageCache::load: Loading en-gb... local cache is empty,global cache is expired/volatile,loading from database
Unstubbing $wgParser on call of $wgParser::firstCallInit from MessageCache->transform
Parser: using preprocessor: Preprocessor_DOM
Unstubbing $wgLang on call of $wgLang::_unstub from ParserOptions->__construct
[MyAEGEEApi] providerAllowsAuthenticationDataChange called
User::getBlockedStatus: checking...
[session] SessionBackend "s0i4jb61ka5ckdhnfqoids1mjb9rl520" data dirty due to dirty(): MediaWiki\Auth\AuthManager->setauthenticationSessionData/MediaWiki\Session\Session->setSecret/MediaWiki\Session\Session->getSecretKeys/MediaWiki\Session\Session->set/MediaWiki\Session\SessionBackend->dirty
[session] SessionBackend "s0i4jb61ka5ckdhnfqoids1mjb9rl520" data dirty due to dirty(): MediaWiki\Auth\AuthManager->setauthenticationSessionData/MediaWiki\Session\Session->setSecret/MediaWiki\Session\Session->getSecretKeys/MediaWiki\Session\Session->set/MediaWiki\Session\SessionBackend->dirty
[session] SessionBackend "s0i4jb61ka5ckdhnfqoids1mjb9rl520" data dirty due to dirty(): MediaWiki\Auth\ThrottlePreAuthenticationProvider->testForauthentication/MediaWiki\Auth\AuthManager->setauthenticationSessionData/MediaWiki\Session\Session->setSecret/MediaWiki\Session\Session->set/MediaWiki\Session\SessionBackend->dirty
[session] SessionBackend "s0i4jb61ka5ckdhnfqoids1mjb9rl520" save: dataDirty=1 metaDirty=0 forcePersist=0
[session] SessionBackend "s0i4jb61ka5ckdhnfqoids1mjb9rl520" data dirty due to dirty(): AuthManagerSpecialPage->performAuthenticationStep/MediaWiki\Auth\AuthManager->beginAuthentication/MediaWiki\Session\Session->setSecret/MediaWiki\Session\Session->set/MediaWiki\Session\SessionBackend->dirty
[session] SessionBackend "s0i4jb61ka5ckdhnfqoids1mjb9rl520" save: dataDirty=1 metaDirty=0 forcePersist=0
[MyAEGEEApi] Got access token
[MyAEGEEApi] Auth succeeded.
[MyAEGEEApi] User succeeded: <user name>
[authentication] Primary login with MyAEGEEApiPrimaryAuthenticationProvider succeeded
[authentication] Auto-creating <user name> on login
[authentication] MediaWiki\Auth\AuthManager::autoCreateUser: IP lacks the ability to create or autocreate accounts
[session] SessionBackend "s0i4jb61ka5ckdhnfqoids1mjb9rl520" data dirty due to dirty(): MediaWiki\Auth\AuthManager->beginAuthentication/MediaWiki\Auth\AuthManager->continueAuthentication/MediaWiki\Auth\AuthManager->autoCreateUser/MediaWiki\Session\Session->set/MediaWiki\Session\SessionBackend->dirty
[session] SessionBackend "s0i4jb61ka5ckdhnfqoids1mjb9rl520" save: dataDirty=1 metaDirty=0 forcePersist=0
[session] SessionBackend "s0i4jb61ka5ckdhnfqoids1mjb9rl520" data dirty due to dirty(): AuthManagerSpecialPage->performAuthenticationStep/MediaWiki\Auth\AuthManager->beginAuthentication/MediaWiki\Auth\AuthManager->continueAuthentication/MediaWiki\Session\Session->remove/MediaWiki\Session\SessionBackend->dirty
[session] SessionBackend "s0i4jb61ka5ckdhnfqoids1mjb9rl520" save: dataDirty=1 metaDirty=0 forcePersist=0
[authevents] Login attempt
[MyAEGEEApi] providerAllowsAuthenticationDataChange called
MediaWiki::preOutputCommit: primary transaction round committed
MediaWiki::preOutputCommit: pre-send deferred updates completed
MediaWiki::preOutputCommit: LBFactory shutdown completed
非常感谢您的回答。