如何只允许已批准的用户登录我的wiki?

时间:2013-03-18 12:37:51

标签: login hook mediawiki

我在名为approved_account的用户表中的wikidatabase中添加了一列。 该列的标准值为0(零)。

我想在用户尝试登录wiki时添加异常,这样就可以了 if approved_account = 0然后拒绝登录尝试。

有谁知道我应该如何以及在哪里放置if语句?


编辑:我走到这一步。 我正在使用AbortLogin钩子,因为每次用户尝试登录时我都需要验证我的语句是否为真。

但是,我的代码不会让任何人进入。它会阻止所有登录尝试,即使我在approved_account字段中有正确的值。 任何人都可以帮我解决这个问题吗?

<?php
/** 
* Prevent a user from accessing this file directly and provide a helpful 
* message explaining how to install this extension.
*/
if ( !defined( 'MEDIAWIKI' ) ) {
    echo <<<EOT
To install the Test extension, put the following line in your LocalSettings.php file: 
require_once( "$IP/extensions/approvedaccount.php" );
EOT;
    exit( 1 );
}

// Extension credits that will show up on Special:Version
$wgExtensionCredits['parserhook'][] = array(
    'name' => 'Approved Account extension',
    'description' => 'Prevent login',
    'author' => 'Me',
    'url' => 'http://www.mediawiki.org/wiki/Extension:approvedaccount'
);
$wgHooks['AbortLogin'][] = 'approvedaccount::onAbortLogin';

class approvedaccount
{
    public static function onAbortLogin( $user, $password, &$retval ) {
    global $wgOut, $wgUser;

    $dbr = wfGetDB( DB_SLAVE );
    $res = $dbr->select(
    'user',                                     // $table
    array( 'user_name', 'approved_account' ),   // $vars (columns of the table)
    'user_name = "'.$wgUser.'"',                // $conds
    __METHOD__,                                 // $fname = 'Database::select',
    array( 'ORDER BY' => 'user_name ASC' )      // $options = array()
    );

    $output = '';
    foreach( $res as $row ) {
    $output .= 'Användarnamn: ' . $row->user_name . ' , Approved Account: ' . $row->approved_account . ".";
    }

    if ($row->approved_account = "1"){
    //$this->loadDefaults();
    //  return false;
    header("Location: http://hbg-whirlpool.emea.stream.corp/index.php?title=Special:UserLogout&returnto=Main+Page");
    exit();  // you need to exit after a Location header is sent
    }   
}
}

1 个答案:

答案 0 :(得分:0)

您可以使用简单的AuthPlugin执行此操作,覆盖strictUserAuth()方法,以便为符合条件的用户返回true。

但是,我怀疑你是以错误的方式接近这个问题。为什么不定义新的user group,比如说approved,然后将相应的记录添加到user_groups table以供批准的用户使用?您将无法阻止未经批准的用户登录,但您 可以仅通过向已批准的群组授予edit权限来阻止他们进行修改,如下所示:

$wgGroupPermissions['*']['edit'] = false;
$wgGroupPermissions['user']['edit'] = false;
$wgGroupPermissions['approved']['edit'] = true;

(如果您愿意,您甚至可以撤销未经批准的用户的read权限,但请先阅读有关restricting read access in MediaWiki的警告。)


修改:我发现您的AbortLogin挂钩存在一些问题。

  • 在钩子中间执行301重定向和exit()可能不是一个好主意。当然,它可能中止登录,但这并不是钩子意味着如何使用。相反,您应该只使用钩子函数return false来指示应该中止登录或true以继续正常的登录检查。

  • 在任何情况下,当exit()列为approved_account时,您正在执行1,这可能恰恰是在不想要中止登录。

  • ...或者更确切地说,您始终在执行exit(),因为您在条件中使用了赋值运算符=而不是比较运算符==,使它永远是真的。 (别担心,这是PHP和其他类C语言中的常见错误。要避免的一种方法是养成使用像1 == $row->approved_account这样的“Yoda条件”的习惯,如果你离开会产生错误输出一个=,因为您无法分配到1。)

  • 此外,将User对象与字符串连接可能不会产生任何有意义的内容;而且,即使它确实如此,那里会有一个SQL注入漏洞。此外,钩子参数已经包含一个User对象,所以你应该使用它而不是全局$wgUser(在登录过程中它可能是陈旧的)。

我承认其中一些内容实际上很难记录。除AbortLogin文档外,我建议查看general MediaWiki hook documentation,以及从SpecialUserlogin.php调用钩子的实际方式。对于数据库访问,我还会指向database wrapper function docs;很遗憾,method documentation pages目前正在提供404错误,因此您需要look directly in the source再次提供文档。

无论如何,我会像这样重写你的钩子:

public static function onAbortLogin( $user, $password, &$retval, &$msg ) {
    $dbr = wfGetDB( DB_SLAVE );
    $row = $dbr->selectRow(
        'user',
        'approved_account',
        array( 'user_id' => $user->getID() ),
        __METHOD__
    );

    if ( !$row || !$row->approved_account ) {
        $retval = LoginForm::ABORTED;  // actually the default, but let's be sure
        $msg = 'login-abort-not-approved';  // optional: custom error message
        return false;
    }
    else {
        // account is approved, return true to proceed with other login checks
        return true;
    }
}

如果您需要自定义消息,还需要在Wiki上创建页面MediaWiki:login-abort-not-approved。 (如果你想把它变成一个合适的MediaWiki扩展,你可以provide a default message in an i18n file,但这可能在这里有点过分了。)


编辑2:是的,您可以在扩展程序中添加任意数量的挂钩。 (事实上​​,你甚至不需要扩展,如果你愿意,可以直接在LocalSettings.php中定义简单的特定于网站的钩子。)我想想的东西像这样可以用AddNewAccount hook来记录用户,虽然我必须注意到我实际上没有测试过这个:

public static function onAddNewAccount( $user, $byEmail ) {
    global $wgUser;
    // try to log out the new user only if they're actually logged in
    if ( $user->getName() == $wgUser->getName() ) $user->logout();
    return true;
}

if子句存在,因为当用户在登录到预先存在的帐户时创建新帐户时也会调用AddNewAccount,在这种情况下从原始帐户中注销它们将是一个不受欢迎的意外。 (从技术上讲,只需if ( $user == $wgUser )即可,但明确比较用户名而不是对象引用似乎更安全。)

请注意,在此时记录新用户会从新的用户创建代码中抽出地毯,因此可能会发生一些不寻常的事情。例如,我怀疑用户创建日志实际上最终可能会说“NewUserName创建新用户帐户NewUserName”,而“帐户成功创建”页面可能会临时显示用户已登录,即使他们实际上是不

首先要以某种方式避免自动登录行为会更加清晰,但是如果不修补SpecialUserlogin.php,我没有看到任何明显的方法:确定新用户是否自动的唯一检查登录的是if ( $this->getUser()->isAnon() ),它只检查用户是否已经登录。就我所知,即使以某种方式伪造(这本身就是一个丑陋的kluge)也不太可行。

如果您不介意修补MediaWiki核心,只需用if ( false )(或if ( false && $this->getUser()->isAnon() )替换该条件,如果您想保持自我记录)应该可以解决问题。请注意,您仍然可以将AddNewAccount挂钩保留为备份,以防您在升级后忘记重新应用补丁或其他内容。