한줄 요약: 아니 이게 무슨 삽질…
놀랍게도 XE와는 다르게 global context 단위에서 Rhymix와 Dokuwiki의 함수가 겹치기 때문에 config/config.inc.php
를 불러오는 것이 불가능하다.
깔끔하게 회원 연동하는 방법이 있을 수도 있지만, 여기서는 그냥 서버에서 원격으로 부를 php 파일을 하나 더 만들고 그 파일을 거쳐서 불러오는 것으로 대체한다.
global context가 겹치는 부분 외에 XE와 Rhymix가 딱히 다른부분이 없기 때문에 XE, Rhymix 둘 다 동일하게 사용할 수 있다.
지난번처럼 preload.php
등을 고칠 필요는 없다.
대신 phpinfo()
에서 allow_url_fopen
이 가능한지, 또한 자신의 서버가 https인 경우에는 OpenSSL이 설치되어있는지까지도 확인한다.
만약 allow_url_fopen
이 되지 않았다면, curl을 쓰든 socket을 직접 불러서 쓰든 알아서 해야 할 것이다.
쿠기 관련도 보안을 위해 각종 옵션들이 켜져있다면 조금 곤란할 수도 있다 ㅜㅜ
doku.php
가 있는 위키 루트 폴더에 userinfo.php
파일을 다음과 같이 만들었다.
PHP 7.4는 될 것이라고 생각하니, const
, []
같은건 적당히 사용했다.
<?php function endsWith( $haystack, $needle ) { $length = strlen( $needle ); if( !$length ) { return true; } return substr( $haystack, -$length ) === $needle; } $baseFile = basename(__FILE__); $scriptName = $_SERVER['SCRIPT_NAME']; if(!endsWith($scriptName, $baseFile)){ return;//혹시나 의도와 다르게 php파일을 부르는 경우를 막기 위해.. } define("__ZBXE__",true); define("__XE__",true); mb_internal_encoding("UTF-8"); mb_regex_encoding("UTF-8"); const SESSION_KEY = "hash 값으로 사용할 아무 문자열, 영문자 적당히 섞어서 16글자쯤"; const XE_PATH = "../xe/config/config.inc.php";//config.inc.php가 있는 경로, rhymix일 수도 있다. $time = $_REQUEST['time']??''; $hash = $_REQUEST['hash']??''; if(!$time || !$hash){ die(json_encode([ 'result'=>false, 'reason'=>'invalid input' ])); } $myTime = time(); $srcTime = intval($time); if(abs($myTime - $srcTime) >= 2){ die(json_encode([ 'result'=>false, 'reason'=>'invalid time' ])); } header("Content-Type: application/json"); if(!file_exists(XE_PATH)){ die(json_encode([ 'result'=>false, 'reason'=>'no path' ])); } if(hash('sha256', SESSION_KEY.$time, false) != $hash){ die(json_encode([ 'result'=>false, 'reason'=>'invalid session hash' ])); } require(XE_PATH); if (!class_exists('Context')) { die(json_encode([ 'result'=>false, 'reason'=>'No XE Context' ])); } $oContext = \Context::getInstance(); $oContext->init(); $logged_info = $oContext->get("logged_info"); if(!$logged_info){ die(json_encode([ 'result'=>true, 'user_id'=>null, 'name'=>null, 'mail'=>null, 'grps'=>null, ])); } die(json_encode([ 'result'=>true, 'user_id'=>$logged_info->user_id, 'name'=>$logged_info->nick_name, 'mail'=>$logged_info->email_address, 'grps'=> @array_values(@array_filter($logged_info->group_list)) ]));
lib/plugins 폴더에 authxe 폴더를 추가하고 아래 파일을 추가했다.
<?php // must be run within Dokuwiki if (!defined('DOKU_INC')) die(); const SESSION_KEY = "위에 적었던 그 문자열을 복사 붙여넣기"; class auth_plugin_authxe extends \dokuwiki\Extension\AuthPlugin { public function __construct() { parent::__construct(); $this->cando['external'] = true; $this->cando['logout'] = false; } function trustExternal($user, $pass, $sticky = false) { global $USERINFO; $baseDir = getBaseURL(true); $targetPath = $baseDir . 'userinfo.php';//만약 위 파일의 경로가 다르다면 여기도 고쳐준다. $arrContextOptions = array( "ssl" => array( "verify_peer" => true, ), "http" => array( 'header' => "Accept-language: ko\r\nCookie: ".session_name()."=".session_id()."\r\n" ) ); $time = ''.time(); $hash = hash('sha256', SESSION_KEY.$time, false); $result = @file_get_contents("{$targetPath}?time={$time}&hash={$hash}", false, stream_context_create($arrContextOptions)); if(!$result){ return false; } $logged_info = json_decode($result); if(!$logged_info->result){ throw new \RuntimeException($logged_info->reason); } if(!$logged_info->user_id){ return false; } $USERINFO['name'] = $logged_info->name; $USERINFO['mail'] = $logged_info->mail; $USERINFO['grps'] = $logged_info->grps; $_SERVER['REMOTE_USER'] = $logged_info->user_id; $_SESSION[DOKU_COOKIE]['auth']['user'] = $logged_info->user_id; $_SESSION[DOKU_COOKIE]['auth']['info'] = $USERINFO; return true; } }
plugin.info.txt
파일이 없으면 또 dokuwiki가 뭐라고 해서 넣어주었다.
base authxe author Hide_D email hided62@gmail.com date 2021-09-23 name AuthXE desc AuthXE, AuthRhymix url https://hided.net
그리고 나서 conf/local.php
의 내용을
$conf['authtype'] = 'authxe'; $conf['disableactions'] = 'register,resendpwd,profile,profile_delete';
정도로 수정해주면 된다.