-->

How do I log into mediawiki using PHP cURL?

2019-04-12 09:32发布

问题:

I'm trying to integrate mediawiki into my website, but I'm having trouble. I think the problem has something to do with the cookies because I get a success from the mediawiki API.

Here's my code:

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

I've also noticed that if I supply a bad token, the API still returns a success, so I can't outrule that, either.

Edit: I've gotten it working perfectly now and updated the code to the current, working code.

回答1:

It looks like you're trying to implement a single sign-on mechanism for your website and MediaWiki by having a PHP script on your website log the user into MediaWiki using the API.

The problem is that, while your script is indeed successfully logging into MediaWiki using the user's credentials, it's not passing the MediaWiki authentication cookies back to the user.

There are a couple of ways to solve this issue:

  • Perhaps the simplest solution would be to handle the MediaWiki login process entirely on the client side using JavaScript / AJAX. That way, the cookies will be sent directly to the users's browser. The down side, of course, is that this won't work for users who cannot or don't want to run JavaScript (but you could always let them just log in to MediaWiki the usual way).

  • You could also do only the first step of the login process (retrieving the token) on the server side, and then have the client request the second step URL directly e.g. by using it as the source of an invisible iframe on the returned HTML page. This doesn't require JavaScript, but does involve sending the user's password and login token back and forth between the server and the client, which could open up security issues. At least, you should make sure you disable caching for the page containing the iframe so that the password will not be saved in the browser cache.

  • Since your website and MediaWiki installation presumably live on the same domain, you could also just use your current code and then set the necessary cookies manually, something like this:

    setcookie( $cookieprefix . '_session', $sessionid );
    setcookie( $cookieprefix . 'UserName', $lgusername );
    setcookie( $cookieprefix . 'UserID',   $lguserid );
    setcookie( $cookieprefix . 'Token',    $lgtoken );
    
  • Finally, you could also turn the problem around, and write a MediaWiki auth plugin to delegate MediaWiki's user authentication to your website's user authentication system instead. This would have the advantage of allowing you to tie the two systems fully together, so that they'd user the same user database and the same authentication cookies. (MediaWiki does still insist on creating its own user records to store its own metadata, but writing an AuthPlugin let you completely override the authentication parts of the system if you want.)