【问题标题】:MediaWiki Authentication from external form来自外部表单的 MediaWiki 身份验证
【发布时间】:2010-11-09 13:08:44
【问题描述】:

我已经安装了 mediawiki ,但是我想让用户通过外部认证表单进行认证。当他们输入正确的用户名和密码时,他们会被重定向到 wiki 页面,并且不需要再次重新输入登录数据,因此他们可以按照他们想要的方式编辑 wiki。我怎样才能做到这一点?

【问题讨论】:

    标签: mediawiki restful-authentication


    【解决方案1】:

    将 mediawiki API 与 action=login 一起使用。见http://en.wikipedia.org/w/api.php

    【讨论】:

      【解决方案2】:

      如果您有提供网络身份验证服务的外部身份验证服务,您可以调整一些网络身份验证扩展This one 在我的组织中使用。当然,您必须对其进行自定义。

      还有一个选项是 OpenID 使用 this extension 登录,看起来类似于 stackoverflow 登录。

      在这两种解决方案中,密码不会在“外部表单”和您的 wiki 之间发送,只是表示用户通过了登录挑战的令牌。

      【讨论】:

      • 非常感谢.. 但是有些人建议我使用“Authplugin”界面.. 你怎么看?
      【解决方案3】:

      另见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==""?'no@email.com':$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);
      ?>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-06-23
        • 2013-11-22
        • 2010-11-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多