3

我正在尝试将 mediawiki 集成到我的网站中,但遇到了麻烦。我认为问题与 cookie 有关,因为我从 mediawiki API 获得了成功。

这是我的代码:

function mw_session_manager($Action = "")
{
    $Root = $_SERVER['SERVER_ADDR'];
    $API_Location = "${Root}/w/api.php";
    $expire = 60*60*24*14 + time();
    $CookieFilePath = tempnam("/tmp/thedirectory", "CURLCOOKIE");
    $CookiePrefix = 'theprefix';
            $Domain = 'thedomain';


    if($Action == 'login')
    {
        // Retrieves email address and password from sign-in form
        $Email = $_POST['LogInEmail'];
        $LgPassword = $_POST['LogInPassword'];
        // Query to retrieve username from database based on email. It is implied that authentication has already succeeded.
        $Query = "SELECT Username FROM Accounts WHERE Email = '$Email'";
        $ResultSet = mysql_query($Query);
        $ResultArray = mysql_fetch_array($ResultSet);
        $LgName = $ResultArray[0]; // Username

        // set variables to use in curl_setopts
        $PostFields = "action=login&lgname=$LgName&lgpassword=$LgPassword&format=php";
        // first http post to sign in to MediaWiki
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, "$API_Location");
        curl_setopt($ch, CURLOPT_POSTFIELDS, "$PostFields");
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_COOKIEJAR, $CookieFilePath);
        curl_setopt($ch, CURLOPT_COOKIEFILE, $CookieFilePath);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        $ResultSerialized = curl_exec($ch);
        curl_close($ch); // curl closed
        $ResultUnserialized = unserialize($ResultSerialized);
        $Token = $ResultUnserialized[login][token];
        // cookie must be set using session id from first response
        $WikiSessionID = $ResultUnserialized[login][sessionid];
        setcookie("${CookiePrefix}_session", $WikiSessionID, $expire, '/', $Domain);

        // second http post to finish sign in
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, "$API_Location");
        curl_setopt($ch, CURLOPT_POSTFIELDS, "action=login&lgname=${LgName}&lgpassword=${LgPassword}&lgtoken=${Token}&format=php");
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_COOKIEJAR, $CookieFilePath);
        curl_setopt($ch, CURLOPT_COOKIEFILE, $CookieFilePath);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

        $ResultSerialized = curl_exec($ch);
        curl_close($ch); // curl closed
        $ResultUnserialized = unserialize($ResultSerialized);

        // set persistent cookies
        $LgToken = $ResultUnserialized["login"]["lgtoken"];
        $LgUserID = $ResultUnserialized["login"]["lguserid"];
        $LgUserName = $ResultUnserialized["login"]["lgusername"];

        setcookie("${CookiePrefix}UserName", $LgUserName, $expire, '/', $Domain);
        setcookie("${CookiePrefix}UserID", $LgUserID, $expire, '/', $Domain);
        setcookie("${CookiePrefix}Token", $LgToken, $expire, '/', $Domain);

        // Delete cURL cookie
        unlink($CookieFilePath);

        return $somedebuggingvariable;
    }
    if($Action = "logout")
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, "$API_Location");
        curl_setopt($ch, CURLOPT_POSTFIELDS, "action=logout");
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_COOKIEJAR, $CookieFilePath);
        curl_setopt($ch, CURLOPT_COOKIEFILE, $CookieFilePath);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        $ResultSerialized = curl_exec($ch);
        $LogoutReturn = unserialize($ResultSerialized);
        $_SESSION['APIReturn'] = $LogoutReturn;
        curl_close($ch); // curl closed

        // destroys persistent cookies and ends session
        $expire = time() - 60*60*24*90;
        setcookie('Session', '', $expire, '/', $Domain);
        setcookie("${CookiePrefix}_session", '', $expire, '/', $Domain);
        setcookie("${CookiePrefix}UserName", '', $expire, '/', $Domain);
        setcookie("${CookiePrefix}UserID", '', $expire, '/', $Domain);
        setcookie("${CookiePrefix}Token", '', $expire, '/', $Domain);

        // delete cURL cookie
        unlink($CookieFilePath);
    }
}

我还注意到,如果我提供了错误的令牌,API 仍然会返回成功,所以我也不能排除这种情况。

编辑:我现在已经让它完美地工作并将代码更新为当前的工作代码。

4

1 回答 1

2

看起来您正在尝试通过在您的网站上使用 PHP 脚本使用 API 将用户登录到 MediaWiki 来为您的网站和 MediaWiki 实现单点登录机制。

问题是,虽然您的脚本确实使用用户的凭据成功登录到 MediaWiki,但它并没有将 MediaWiki 身份验证 cookie 传递回用户。

有几种方法可以解决这个问题:

  • 也许最简单的解决方案是使用 JavaScript / AJAX 完全在客户端处理 MediaWiki 登录过程。这样,cookie 将直接发送到用户的浏览器。当然,不利的一面是这对不能或不想运行 JavaScript 的用户不起作用(但您总是可以让他们以通常的方式登录 MediaWiki)。

  • 您也可以只在服务器端执行登录过程的第一步(检索令牌),然后让客户端直接请求第二步 URL,例如将其用作iframe返回的 HTML 页面上不可见的源。这不需要 JavaScript,但确实涉及在服务器和客户端之间来回发送用户的密码和登录令牌,这可能会引发安全问题。至少,您应该确保禁用包含 的页面的缓存,iframe以便密码不会保存在浏览器缓存中。

  • 由于您的网站和 MediaWiki 安装可能位于同一个域中,因此您也可以只使用当前代码,然后手动设置必要的 cookie,如下所示:

    setcookie( $cookieprefix . '_session', $sessionid );
    setcookie( $cookieprefix . 'UserName', $lgusername );
    setcookie( $cookieprefix . 'UserID',   $lguserid );
    setcookie( $cookieprefix . 'Token',    $lgtoken );
    
  • 最后,您还可以扭转问题,编写一个MediaWiki 身份验证插件,将 MediaWiki 的用户身份验证委托给您网站的用户身份验证系统。这样做的好处是允许您将两个系统完全绑定在一起,以便它们使用相同的用户数据库和相同的身份验证 cookie。(MediaWiki 仍然坚持创建自己的用户记录来存储自己的元数据,但是编写一个 AuthPlugin 可以让您完全覆盖系统的身份验证部分,如果您愿意。)

于 2013-01-01T21:04:13.540 回答