0

我在我的 wiki 数据库中的用户表中添加了一个名为approved_account. 该列的标准值为0(零)。

当用户尝试登录 wiki 时,我想添加一个异常,这样如果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
    }   
}
}
4

1 回答 1

0

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

但是,我怀疑您以错误的方式处理此问题。为什么不直接定义一个新的用户组,比如,approved然后将相应的记录添加到user_groups 表中以获得批准的用户?您将无法阻止未经批准的用户登录,但您可以edit通过仅向已批准的组授予权限来阻止他们进行编辑,如下所示:

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

(如果您愿意,您甚至可以撤销read未经批准的用户的许可,但请先阅读有关限制 MediaWiki 中的读取访问权限的警告。)


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

  • 做一个 301 重定向和一个exit()在钩子中间可能不是一个好主意。当然,它可能中止登录,但这并不是钩子的真正用途。相反,您应该只返回挂钩函数false以指示应该中止登录或true继续进行正常的登录检查。

  • 无论如何,您正在执行exit()when the approved_account column is 1,这可能正是您不想中止登录的时候。

  • ...或者,更确切地说,您一直在做exit(),因为您在条件中使用了赋值运算符=而不是比较运算符==,导致它始终为真。(别担心,这是 PHP 和其他类 C 语言中的常见错误。避免的一种方法是养成使用“尤达条件”之类的习惯,1 == $row->approved_account如果您遗漏一个,这将产生错误=,因为您不能分配给1.)

  • 此外,将 User 对象与字符串连接可能不会产生任何有意义的东西。而且,即使它确实存在,那里也会存在 SQL 注入漏洞。此外,钩子参数已经包含一个 User 对象,因此您应该使用它而不是全局对象$wgUser(无论如何这在登录期间可能已经过时)。

我承认其中一些东西的文档记录确实很差。除了AbortLogin文档,我建议查看通用 MediaWiki 钩子文档,以及从SpecialUserlogin.php调用钩子的实际方式。对于数据库访问,我还会向您指出数据库包装函数 docs;不幸的是,方法文档页面现在给出了 404 错误,因此您需要再次直接查看文档的源代码。

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

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;
    }
}

如果您想要自定义消息,您还需要MediaWiki:login-abort-not-approved在您的 wiki 上创建页面。(如果你想把它变成一个适当的 MediaWiki 扩展,你可以在 i18n 文件中提供一个默认消息,但这在这里可能有点过分了。)


编辑 2:是的,您可以在扩展中添加任意数量的挂钩。(事实上​​,您甚至不需要扩展,如果您愿意,可以直接在 LocalSettings.php 中定义简单的特定于站点的挂钩。)我认为这样的事情可以用于AddNewAccount 挂钩来注销用户,虽然我必须注意我还没有实际测试过这个:

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 挂钩作为备份,以防您在升级或其他情况后忘记重新应用补丁。

于 2013-03-21T12:15:06.843 回答