如何使用PHP cURL登录mediawiki?

如何使用PHP cURL登录mediawiki?,php,cookies,curl,mediawiki-api,Php,Cookies,Curl,Mediawiki Api,我试图将mediawiki集成到我的网站中,但遇到了问题。我认为问题与cookies有关,因为我从mediawiki API获得了成功 这是我的密码: function mw_session_manager($Action = "") { $Root = $_SERVER['SERVER_ADDR']; $API_Location = "${Root}/w/api.php"; $expire = 60*60*24*14 + time(); $CookieFileP

我试图将mediawiki集成到我的网站中,但遇到了问题。我认为问题与cookies有关,因为我从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仍然会返回一个成功,因此我也不能排除这一点


编辑:我现在已经让它工作得很好,并将代码更新为当前的工作代码。

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

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

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

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

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

  • 由于您的网站和MediaWiki安装可能位于同一个域中,因此您也可以使用当前代码,然后执行如下操作:

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


你看了吗?是的,那是我使用的指南之一。我已经更新了代码,以更紧密地遵循这个特定的示例,因为它是最好的一个…那么,一旦您有了返回值,您将如何处理它们呢?想必您必须以某种方式将cookies传递给客户机——也许问题就在那里?(顺便说一句,我测试了你的代码,就目前而言,它确实适合我。)太棒了!没什么,我不知道怎么做。我刚刚学习了http头和cookie,所以对我来说这是全新的。如果你愿意,解释一下你是怎么做的?我注意到你的代码有很多错误,PHP应该提醒你。(例如,
'login\u userid'
不应该是
'login\u lguserid'
?)您确实应该启用错误日志记录(最好将报告级别设置为
E\u ALL
)并修复您看到的任何警告。此外,成功登录后返回的
lgtoken
值与第一次尝试后返回的
token
值不同。在盲目尝试第二个API查询之前,还应该检查第一个API查询返回的内容。谢谢,它现在可以工作了!我现在手动设置cookies。我以前试过,我想我有一些成功,但是太少了,我以为我忘记了注销--我忘记了登录尝试之间需要5秒的时间。但是仍然有一个问题——如果我尝试登录失败,因为我没有等待足够长的时间,那么在我通过实际的mediawiki表单登录并注销之前,它不会让我再次通过API登录。我想你只需要等待5分钟的超时过期。如果需要,您可以在LocalSettings.php中通过设置(比如,
$wgPasswordAttemptThrottle['seconds']=60)来降低它。或者,您甚至可以使用
if($\u server['REMOTE\u ADDR']=='127.0.0.1')$wgPasswordAttemptThrottle=false)之类的命令豁免来自同一服务器的请求进行限制。(当然,如果您这样做,那么最好实现您自己的登录尝试限制。实际上,在任何情况下,这都是一个好主意。)我认为这不是限制问题。我刚刚关闭了节流阀,我仍然有同样的问题。一次登录失败将阻止以后登录。即使成功,它也只在主页上注册为已登录,并且只有在登录后第一次访问主页时才注册。除非我在访问mediawiki页面之前等待15秒,否则它根本不会将我注册为已登录;如果我这样做,我会被完全锁定,直到我使用mediawiki登录表单登录;我不知道是什么原因造成的。API对失败的登录尝试(以及随后的登录尝试)报告了什么结果?好吧,我现在已经彻底解决了这个问题。原来浏览器缓存显示我仍然登录了一些页面;这与MediaWiki无关。现在已经完全修好了。我将更新代码,以防将来有人遇到类似问题。它现在内置了一个注销例程。谢谢你的帮助!