问题
I have already installed mediawiki , but I want to make users authenticate from external authentication form.When they enter the right username and password , they are redirected to the wiki page and do not need to retype the Login data again , and hence they can go to edit the wiki the way they want.How can I achieve that?
回答1:
Use the mediawiki API with action=login . See http://en.wikipedia.org/w/api.php
回答2:
If you have external authentication service that provides web authenticaion service you can adapt some webauth extension. This one is used in my organization. You will have to customize it of course.
Yet another option is OpenID login with this extension, looks similar to stackoverflow login.
In these two solutions password is not sent between the "external form" and your wiki, only a token signifying that user passed the login challenge.
回答3:
see also https://www.mediawiki.org/wiki/User:Krinkle/API_PHP_cURL_example
simple code:
<?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¶m2=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);
?>
来源:https://stackoverflow.com/questions/1106611/mediawiki-authentication-from-external-form