MediaWiki Аутентификация из внешней формы

Я уже установил mediawiki, но я хочу, чтобы пользователи аутентифицировались из внешней формы аутентификации. Когда они вводят правильное имя пользователя и пароль, они перенаправляются на страницу вики, и им не нужно повторно вводить данные для входа, и, следовательно, они могут идти редактировать вики так, как они хотят. Как мне этого добиться?


person Mohammed Abdullatif    schedule 09.07.2009    source источник


Ответы (3)


Используйте API медиавики с action=login . См. http://en.wikipedia.org/w/api.php.

person Pierre    schedule 09.07.2009

Если у вас есть внешняя служба аутентификации, предоставляющая услугу веб-аутентификации, вы можете адаптировать некоторое расширение веб-аутентификации. Это один используется в моей организации. Конечно, вам придется настроить его.

Еще одним вариантом является вход OpenID с этим расширением, похоже на вход в систему через stackoverflow.

В этих двух решениях пароль не отправляется между «внешней формой» и вашей вики, а только токен, указывающий, что пользователь прошел вход в систему.

person Evgeny    schedule 16.07.2009
comment
Большое спасибо .. но некоторые люди посоветовали мне интерфейс Authplugin .. Что вы думаете? - person Mohammed Abdullatif; 16.07.2009

см. также https://www.mediawiki.org/wiki/User:Krinkle/API_PHP_cURL_example

простой код:

<?php

// Retrieves email address and password from sign-in form
$Username = array_key_exists('username',$_REQUEST)?$_REQUEST['username']:'';
$Password = array_key_exists('password',$_REQUEST)?$_REQUEST['password']:'';
$Action = array_key_exists('action',$_REQUEST)?$_REQUEST['action']:'';


$API_Location = "http://127.0.0.1/w/api.php";

//copied from LocalSettings.php

$wgDBtype = "mysql";
$wgDBserver = "localhost";
$wgDBname = "wiki";
$wgDBuser = "myuser";
$wgDBpassword = "12312312";

$CookiePrefix = 'wiki';

$expire = 60*60*24*365*5 + time();
$CooiePath= null; //='/';
$CookieDomain = null; //'example.com';




function encodeURIComponent($str) {
    $revert = array('%21'=>'!', '%2A'=>'*', '%27'=>"'", '%28'=>'(', '%29'=>')');
    return strtr(rawurlencode($str), $revert);
}


class curl_onHeaders
{
    public $result=array();
    function onHeader( $curl, $header_line ) {
        $this->result[]=$header_line;
        return strlen($header_line);
    }
}

function curl($method,$url,$data=false,$headers=false)
{
    //$method="PUT"
    //$url ="http://example.com";
    //$data = "The updated text message";
    //$headers=array();  $headers[] = 'Accept: text/html';
    $ch = curl_init();
    if($data!==false)
    {
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch,CURLOPT_POSTFIELDS,$data); // any post data, a string like param1=a&param2=b
    }
    if($headers!==false)
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);  
    curl_setopt($ch, CURLOPT_URL,$url);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);  //for updating we have to use PUT method.
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 


    $onHeader = new curl_onHeaders();
    curl_setopt($ch, CURLOPT_HEADERFUNCTION, array(&$onHeader, 'onHeader'));

    $result = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    $object = new stdClass();
    $object->result = $result;
    $object->code = $code;
    $object->headers = $onHeader->result;

    if(curl_errno($ch))
              throw new Exception("curl error: ".  curl_error($ch)); 
              //$object->error =curl_error($ch);

    return $object;
}




function getcookies($headers)
{
    $cookies='';
    foreach( $headers as $header)
    {
        if (preg_match('/^Set-Cookie:\s*([^;]*)/mi', $header, $cookie) == 1)
        {
            if($cookies==='')
                $cookies = $cookie[1];
            else
                $cookies .="; ".$cookie[1];
        }
    }
    return $cookies;
}

function mearge_cookies($old,$new)
{
    // cookies like session are sent only once from server, multiple cookies generally can be mearged  with "; "
    // a cookie jar is prefered  but this code generally fine.
    // folowing code does not handle expires
    //
    // cookie format: https://msdn.microsoft.com/en-us/library/windows/desktop/aa384321(v=vs.85).aspx
    //
    // Set-Cookie: <name>=<value>[; <name>=<value>]...
    // [; expires=<date>][; domain=<domain_name>]
    // [; path=<some_path>][; secure][; httponly]
    //
    // <date> format:
    // DAY, DD-MMM-YYYY HH:MM:SS GMT
    // DAY The day of the week (Sun, Mon, Tue, Wed, Thu, Fri, Sat).
    // DD The day in the month (such as 01 for the first day of the month).
    // MMM The three-letter abbreviation for the month (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec).
    // YYYY The year.
    // HH The hour value in military time (22 would be 10:00 P.M., for example).
    // MM The minute value.
    // SS The second value.


    $cookiesa=array();
    $cookies_strs_to_merge=array($old,$new);
    foreach($cookies_strs_to_merge as $cookies_str)
    {
        foreach(preg_split("/\\s*;\\s*/",$cookies_str) as $cookie)
        {
         $pcookie=preg_split("/\\s*=\\s*/",$cookie);
         $cookie_name=$pcookie[0];
         $cookie_value=$pcookie[1];
         if(sizeof($pcookie)>1)
         {
             if($cookie_name=='domain') continue;
             if($cookie_name=='expires') continue;
             if($cookie_name=='path') continue;
            $cookiesa[$cookie_name]=$cookie_value;
         }
         else if($cookie=='secure' )continue;
         else if($cookie=='httponly' )continue;
        }
    }
    $cookies='';
    foreach($cookiesa as $cookie_name=>$cookie_value)
     $cookies.=($cookies===''?'':'; ').$cookie_name.'='.$cookie_value;
 return $cookies;
}
//echo mearge_cookies("aaa=vsdfvsdfv; bbb=asdfasdfasf","aaa=222; ccc=123123"); die;

//$res=curl("GET",'http://doodkin.com');
//$lastcookies=getcookies($res->headers);
//$res=curl("GET",'http://doodkin.com',false,array('Cookie: '.$lastcookies));
//$lastcookies=mearge_cookies($lastcookies, getcookies($res->headers) );


mysql_connect($wgDBserver, $wgDBuser, $wgDBpassword) or die('Could not connect: ' . mysql_error());


if($Action == 'login')
{ 



    // Query to retrieve username from database based on email. It is implied that authentication has already succeeded.
    $Query = "SELECT Username FROM `$wgDBname`.Accounts WHERE Email = '".mysql_escape_string($Username)."'";
    $ResultSet = mysql_query($Query);
    if(mysql_num_rows($Query))
    {
        $ResultArray = mysql_fetch_array($ResultSet);
        $Username = $ResultArray[0]; // Username
    }
    mysql_free_result($ResultSet);



    // first http post to sign in to MediaWiki  
    $res=curl("POST",$API_Location,"action=login&lgname=".encodeURIComponent($Username)."&lgpassword=".encodeURIComponent($Password)."&format=php");
    $lastcookies=getcookies($res->headers);
    $result = unserialize($res->result);
    $Token = $result[login][token];

    // cookie must be set using session id from first response
    $WikiSessionID = $result[login][sessionid];
    setcookie("${CookiePrefix}_session", $WikiSessionID, $expire, $CooiePath, $CookieDomain);

    // second http post to finish sign in
    if ($result["login"]["result"] == "NeedToken") {
        $res=curl("POST",$API_Location,"action=login&lgname=".encodeURIComponent($Username)."&lgpassword=".encodeURIComponent($Password)."&lgtoken=".encodeURIComponent($Token)."&format=php",array('Cookie: '.$lastcookies));
        $result = unserialize($res->result);
    }


     if ($result["login"]["result"] == "Success") {
        $error = 'ok';


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

        if($cookieprefix!=$CookiePrefix) throw new Exception('notice a wrong cookie prefix');


        $_COOKIE["${CookiePrefix}UserName"]=$LgUserName;
        $_COOKIE["${CookiePrefix}UserID"]=$LgUserID;
        $_COOKIE["${CookiePrefix}Token"]=$LgToken;
        $_COOKIE["${CookiePrefix}_session"]=$WikiSessionID;


        setcookie("${CookiePrefix}UserName", $LgUserName, $expire, $CooiePath, $CookieDomain);
        setcookie("${CookiePrefix}UserID", $LgUserID, $expire, $CooiePath, $CookieDomain);
        setcookie("${CookiePrefix}Token", $LgToken, $expire, $CooiePath, $CookieDomain);
    } else if ($result["login"]["result"] == "NeedToken") {
        $error = "Error 005: Token error. second request.";

    } else if ($result["login"]["result"] == "NoName") {
        $error =  "The username can not be blank";

    } else if ($result["login"]["result"] == "Illegal") {
        $error =  "You provided an illegal username";

    } else if ($result["login"]["result"] == "NotExists") {
        $error =  "The username you provided doesn't exist";

    } else if ($result["login"]["result"] == "EmptyPass") {
        $error =  "The password can not be blank";

    } else if ($result["login"]["result"] == "WrongPass" || $result["login"]["result"] == "WrongPluginPass") {
        $error =  "The password you provided is incorrect";

    } else if ($result["login"]["result"] == "CreateBlocked") {
        $error =  "Autocreation was blocked from this IP address";

    } else if ($result["login"]["result"] == "Throttled") {
        $error =  "You've logged in too many times in a short time. Try again later.";

    } else if ($result["login"]["result"] == "mustbeposted") {
        $error =  "Error 004: Logindata was not send correctly";

    } else if ($result["login"]["result"] == "Blocked") {
        $error =  "This account is blocked.";

    } else if ($result["login"]["result"]){
        $error = "Error 001: An unknown event occurred.";
    } else {
        $error = "Error 002: An unknown event occurred.";
    }

    echo $error;
}


if($Action == "logout")
{
        // first http post to sign in to MediaWiki  

    $_session = array_key_exists("${CookiePrefix}_session",$_COOKIE)?$_COOKIE["${CookiePrefix}_session"]:'';
    $UserName = array_key_exists("${CookiePrefix}UserName",$_COOKIE)?$_COOKIE["${CookiePrefix}UserName"]:'';
    $UserID = array_key_exists("${CookiePrefix}UserID",$_COOKIE)?$_COOKIE["${CookiePrefix}UserID"]:'';
    $Token = array_key_exists("${CookiePrefix}Token",$_COOKIE)?$_COOKIE["${CookiePrefix}Token"]:'';

    $headers=array( "Cookie: ". 
           "${CookiePrefix}_session=".encodeURIComponent($_session)."; ". 
           "${CookiePrefix}UserName=".encodeURIComponent($UserName)."; ". 
           "${CookiePrefix}UserID=".encodeURIComponent($UserID)."; ". 
           "${CookiePrefix}Token=".encodeURIComponent($Token) );

    $res=curl("POST",$API_Location,"action=logout",$headers);

    $LogoutReturn = unserialize($res->result);

    // destroys persistent cookies and ends session
    $expire = time() - 60*60*24*90;

    setcookie('Session', '', $expire, $CooiePath, $CookieDomain);
    setcookie("${CookiePrefix}_session", '', $expire, $CooiePath, $CookieDomain);
    setcookie("${CookiePrefix}UserName", '', $expire, $CooiePath, $CookieDomain);
    setcookie("${CookiePrefix}UserID", '', $expire, $CooiePath, $CookieDomain);
    setcookie("${CookiePrefix}Token", '', $expire, $CooiePath, $CookieDomain);

        unset($_COOKIE["${CookiePrefix}UserName"]);
        unset($_COOKIE["${CookiePrefix}UserID"]);
        unset($_COOKIE["${CookiePrefix}Token"]);
        unset($_COOKIE["${CookiePrefix}_session"]);


  echo "logout";
}

function checklogin()
{
    global $CookiePrefix,$wgDBname;
    if( array_key_exists("${CookiePrefix}_session",$_COOKIE)
        && array_key_exists("${CookiePrefix}UserID",$_COOKIE)
    )
    {

        $UserID = intval($_COOKIE["${CookiePrefix}UserID"]);
        $UserName = array_key_exists("${CookiePrefix}UserName",$_COOKIE)?$_COOKIE["${CookiePrefix}UserName"]:'';
        $Token = array_key_exists("${CookiePrefix}Token",$_COOKIE)?$_COOKIE["${CookiePrefix}Token"]:'';

        ($result=mysql_query("Select user_name,user_real_name,user_email,user_token,user_token,(Select ug_user from `$wgDBname`.user_groups  WHERE ug_group='sysop' and ug_user=user.user_id) as perms from `$wgDBname`.user user WHERE user_id=$UserID"))||die(mysql_error());
                $udata=mysql_fetch_object($result);
                mysql_free_result($result);

        if ($udata!=null)
        {
            if ( $udata->perms!=null )
            {
                $level = 1;
            }

            if($UserName!=$udata->user_name)
            {
                echo "different username. cookie vs db. can not auto login from mediawiki";
                return null;
            }

            if($Token!=$udata->user_token) {
                echo "different token. cookie vs db. can not auto login from mediawiki";
                return null;
            }

            return array(
                'UniqueID' => $UserID,
                'Name' => $UserName,
                'Title' => $udata->user_real_name==""?NULL:$udata->user_real_name,
                'Email' => $udata->user_email==""?'[email protected]':$udata->user_email,
                'Admin' => $level
            );
        }
        return null;

    }
}

?>
<?

$user=checklogin();
if($user!=null)
{
    ?>
     welcome <?=$user['Title']? $user['Title']:$user['Name'] ?>. <br>
     <a href="<?=$_SERVER['PHP_SELF']?>?action=logout">logout</a>
    <?
}
else
{
    ?>

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->

    <title>Signin</title>

    <!-- Bootstrap core CSS -->
    <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha/css/bootstrap.css" rel="stylesheet">

<!--[if eq IE 10]>
<style type="text/css">
/*!
 * IE10 viewport hack for Surface/desktop Windows 8 bug
 * http://getbootstrap.com/getting-started/#support-ie10-width
 */
@-webkit-viewport { width: device-width; }
@-moz-viewport    { width: device-width; }
@-ms-viewport     { width: device-width; }
@-o-viewport      { width: device-width; }
@viewport         { width: device-width; }
</style>


    <![endif]-->

    <!-- Custom styles for this template -->
    <style type="text/css">
    body {
      padding-top: 40px;
      padding-bottom: 40px;
      background-color: #eee;
    }

    .form-signin {
      max-width: 330px;
      padding: 15px;
      margin: 0 auto;
    }
    .form-signin .form-signin-heading,
    .form-signin .checkbox {
      margin-bottom: 10px;
    }
    .form-signin .checkbox {
      font-weight: normal;
    }
    .form-signin .form-control {
      position: relative;
      height: auto;
      -webkit-box-sizing: border-box;
         -moz-box-sizing: border-box;
              box-sizing: border-box;
      padding: 10px;
      font-size: 16px;
    }
    .form-signin .form-control:focus {
      z-index: 2;
    }
    .form-signin input[type="email"] {
      margin-bottom: -1px;
      border-bottom-right-radius: 0;
      border-bottom-left-radius: 0;
    }
    .form-signin input[type="password"] {
      margin-bottom: 10px;
      border-top-left-radius: 0;
      border-top-right-radius: 0;
    }
    </style>

    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
    <!--[if lt IE 9]>
      <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
      <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
  </head>

  <body>

    <div class="container">

      <form class="form-signin" action="<?=$_SERVER['PHP_SELF']?>" method="post" ><input type="hidden" name="action" value="login">
        <h2 class="form-signin-heading">Please sign in</h2>
        <label for="inputEmail" class="sr-only">Username or Email address</label>
        <input type="text" id="inputEmail" class="form-control" name="username" placeholder="Username Or Email address" required autofocus>
        <label for="inputPassword" class="sr-only">Password</label>
        <input type="password" id="inputPassword" name="password" class="form-control" placeholder="Password" required>
        <!-- <div class="checkbox">
          <label>
            <input type="checkbox" value="remember-me"> Remember me
          </label>
        </div> -->
        <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
      </form>

    </div> <!-- /container -->


    <!--[if eq IE 10]>
<script type="application/javascript">
/*!
 * IE10 viewport hack for Surface/desktop Windows 8 bug
 * Copyright 2014-2015 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 */

// See the Getting Started docs for more information:
// http://getbootstrap.com/getting-started/#support-ie10-width

(function () {
  'use strict';

  if (navigator.userAgent.match(/IEMobile\/10\.0/)) {
    var msViewportStyle = document.createElement('style')
    msViewportStyle.appendChild(
      document.createTextNode(
        '@-ms-viewport{width:auto!important}'
      )
    )
    document.querySelector('head').appendChild(msViewportStyle)
  }

})();
    </script>
    <![endif]-->
  </body>
</html>
    <?
}
@mysql_close($conn);
?>
person Shimon Doodkin    schedule 15.02.2016