我现在运行PHPBB论坛一段时间,我的目标是使用其用户管理和身份验证功能创建一个Zend2 程序,而不是建立一个全新的授权组件,从而需要再次与论坛同步.
以下组件将在实时环境中使用:PHPBB3,Zend Framework 2(最新版本),Apache,PHP 5.6,在无root访问权限的虚拟Linux服务器上运行的MysqL.
我的开发环境(运行所有示例)是:PHPBB3,XAMPP 3.2.2,PHP 5.6.21启用xdebug,MariaDB在Windows 8上运行.
global $PHPbb_root_path,$PHPEx,$user,$db,$config,$cache,$template; define('IN_PHPBB',true); $PHPbb_root_path = './forum/PHPBB3/'; // this path is from an external example $PHPEx = substr(strrchr(__FILE__,'.'),1); $PHPBBFile = $PHPbb_root_path . 'common.' . $PHPEx; include($PHPBBFile); // Start session management $user->session_begin(); $auth->acl($user->data); $user->setup();
我已经取得了成功,包括没有使用框架的人,或直接通过ajax直接调用PHP,但是现在使用Zend 2框架 – 当包含本机PHPBB3代码时,会出现多个问题.
我不得不说我不是一个经验丰富的PHP程序员,而且我一直在学习Zend几天.
我的第一个尝试集中在Zend应用程序在Zend index.PHP之前调用上面的代码:
.... // Setup autoloading require 'init_autoloader.PHP'; global $PHPbb_root_path,true); $PHPbb_root_path = 'public/forums/'; $PHPEx = substr(strrchr(__FILE__,1); $PHPBBFile = $PHPbb_root_path . 'common.' . $PHPEx; include($PHPBBFile); // Run the application! Zend\Mvc\Application::init(require 'config/application.config.PHP')->run(); ....
导致此错误:
Catchable fatal error: Argument 1 passed to Zend\Stdlib\Parameters::__construct() must be of the type array,
object given,called in C:\xampp\htdocs\myZendApp\vendor\zendframework\zend-http\src\PHPEnvironment\Request.PHP
on line 72 and defined in C:\xampp\htdocs\myZendApp\vendor\zendframework\zend-stdlib\src\Parameters.PHP on line 24
所以早点调用PHPBB似乎搞砸了Zend的坏方式,我继续其他的实现.
我喜欢的设计将包括一个单独的身份验证Zend模块,它处理PHPBB身份验证,并可作为所有路由及其控制器的服务使用.
然而,包括和调用PHPbb脚本会导致与全局变量大量使用有关的各种问题.
这里有一些来自PHPbbAuthController中的checkAction的示例代码:
public function checkAction(){ global $PHPbb_root_path,$template; define('IN_PHPBB',true); $PHPbb_root_path = 'public/forums/'; $PHPEx = substr(strrchr(__FILE__,1); $PHPBBFile = $PHPbb_root_path . 'common.' . $PHPEx; include($PHPBBFile); $user->session_begin(); $auth->acl($user->data); $user->setup(); $response = array(); if ($user->data['user_id'] == ANONYMOUS) { $response['loginState'] = "logged_out"; } else { $response['loginState'] = "logged_in"; } return new viewmodel($response); }
这里执行session_begin()的错误
Fatal error: Call to a member function header() on null in
C:\xampp\htdocs\myZendApp\public\forums\PHPbb\session.PHP on line 228
调试完成后,似乎所有对$request和$symfony_request的引用都在那些认证函数里面是NULL.
在沉迷了许多小时后,从Zend上下文中挑选出一种执行脚本的方法,我已经设法在一个单独的上下文中执行脚本的方式.
我想到的最简单的方法是从HttpClient调用脚本,并使用结果文本来驱动我的认证服务.
为此,我需要从被调用的脚本中检索会话cookie,并将其存储在Zend应用程序中.
如果我通过Zend Framework引导脚本,我似乎又遇到了同样的问题(在Zend控制器中有PHBB代码),所以我不能使用Zend路由来访问它们.
由于我使用http请求,我必须将脚本存储在公用目录或其子目录中.
那就是我现在的地方.使用PHPBB的PHP文件的内部调用自己工作正常,但是我使用的(从现在的Zend Controller类)的HttpClient在每一个回合都遇到了一个超时,我在另一个问题上写道:Zend 2 Http Client Request times out when requesting php file from localhost/public directory.
我会感谢您的意见,提示和可能的架构,甚至部分解决我上面提到的问题.
在任何情况下我不想做的是发明自己的身份验证和用户管理,因为它总是比已经在PHPBB中的复杂但经过验证的系统更差,并导致长期的安全问题.
此外,Zend应用程序被认为是“Extra”,因为论坛是站点的核心.
请看看:
https://github.com/phpbb/phpbb/blob/3.1.x/phpBB/config/auth.yml(容器对PHPBB3认证提供程序的定义)
版主在
https://github.com/phpbb/phpbb/blob/master/phpBB/config/default/container/services_auth.yml
和
https://github.com/phpbb/phpbb/blob/3.1.x/phpBB/phpbb/auth/provider/provider_interface.php(如下图所示)
<?PHP /** * * This file is part of the PHPBB Forum Software package. * * @copyright (c) PHPBB Limited <https://www.PHPbb.com> * @license GNU General Public License,version 2 (GPL-2.0) * * For full copyright and license information,please see * the docs/CREDITS.txt file. * */ namespace PHPbb\auth\provider; /** * The interface authentication provider classes have to implement. */ interface provider_interface { /** * Checks whether the user is currently identified to the authentication * provider. * Called in acp_board while setting authentication plugins. * Changing to an authentication provider will not be permitted in acp_board * if there is an error. * * @return boolean|string False if the user is identified,otherwise an * error message,or null if not implemented. */ public function init(); /** * Performs login. * * @param string $username The name of the user being authenticated. * @param string $password The password of the user. * @return array An associative array of the format: * array( * 'status' => status constant * 'error_msg' => string * 'user_row' => array * ) * A fourth key of the array may be present: * 'redirect_data' This key is only used when 'status' is * equal to LOGIN_SUCCESS_LINK_PROFILE and its value is an * associative array that is turned into GET variables on * the redirect url. */ public function login($username,$password); /** * Autologin function * * @return array|null containing the user row,empty if no auto login * should take place,or null if not impletmented. */ public function autologin(); /** * This function is used to output any required fields in the authentication * admin panel. It also defines any required configuration table fields. * * @return array|null Returns null if not implemented or an array of the * configuration fields of the provider. */ public function acp(); /** * This function updates the template with variables related to the acp * options with whatever configuraton values are passed to it as an array. * It then returns the name of the acp file related to this authentication * provider. * @param array $new_config Contains the new configuration values that * have been set in acp_board. * @return array|null Returns null if not implemented or an array with * the template file name and an array of the vars * that the template needs that must conform to the * following example: * array( * 'TEMPLATE_FILE' => string,* 'TEMPLATE_VARS' => array(...),* ) * An optional third element may be added to this * array: 'BLOCK_VAR_NAME'. If this is present,* then its value should be a string that is used * to designate the name of the loop used in the * ACP template file. When this is present,an * additional key named 'BLOCK_VARS' is required. * This must be an array containing at least one * array of variables that will be assigned during * the loop in the template. An example of this is * presented below: * array( * 'BLOCK_VAR_NAME' => string,* 'BLOCK_VARS' => array( * 'KEY IS UNIMPORTANT' => array(...),* ),* 'TEMPLATE_FILE' => string,* ) */ public function get_acp_template($new_config); /** * Returns an array of data necessary to build custom elements on the login * form. * * @return array|null If this function is not implemented on an auth * provider then it returns null. If it is implemented * it will return an array of up to four elements of * which only 'TEMPLATE_FILE'. If 'BLOCK_VAR_NAME' is * present then 'BLOCK_VARS' must also be present in * the array. The fourth element 'VARS' is also * optional. The array,with all four elements present * looks like the following: * array( * 'TEMPLATE_FILE' => string,* 'BLOCK_VAR_NAME' => string,* 'BLOCK_VARS' => array(...),* 'VARS' => array(...),* ) */ public function get_login_data(); /** * Performs additional actions during logout. * * @param array $data An array corresponding to * \PHPbb\session::data * @param boolean $new_session True for a new session,false for no new * session. */ public function logout($data,$new_session); /** * The session validation function checks whether the user is still logged * into PHPBB. * * @param array $user * @return boolean true if the given user is authenticated,false if the * session should be closed,or null if not implemented. */ public function validate_session($user); /** * Checks to see if $login_link_data contains all information except for the * user_id of an account needed to successfully link an external account to * a forum account. * * @param array $login_link_data Any data needed to link a PHPBB account to * an external account. * @return string|null Returns a string with a language constant if there * is data missing or null if there is no error. */ public function login_link_has_necessary_data($login_link_data); /** * Links an external account to a PHPBB account. * * @param array $link_data Any data needed to link a PHPBB account to * an external account. */ public function link_account(array $link_data); /** * Returns an array of data necessary to build the ucp_auth_link page * * @param int $user_id User ID for whom the data should be retrieved. * defaults to 0,which is not a valid ID. The method * should fall back to the current user's ID in this * case. * @return array|null If this function is not implemented on an auth * provider then it returns null. If it is implemented * it will return an array of up to four elements of * which only 'TEMPLATE_FILE'. If 'BLOCK_VAR_NAME' is * present then 'BLOCK_VARS' must also be present in * the array. The fourth element 'VARS' is also * optional. The array,* ) */ public function get_auth_link_data($user_id = 0); /** * Unlinks an external account from a PHPBB account. * * @param array $link_data Any data needed to unlink a PHPBB account * from a PHPbb account. */ public function unlink_account(array $link_data); }
您可以实现为您的Zend框架项目创建提供程序的界面.
创建会话后,可以看到提供者如何使用
https://github.com/phpbb/phpbb/blob/master/phpBB/phpbb/session.php#L560
/* @var $provider_collection \PHPbb\auth\provider_collection */ $provider_collection = $PHPbb_container->get('auth.provider_collection'); $provider = $provider_collection->get_provider(); $this->data = $provider->autologin();
确保两个项目都使用相同的Cookie,或者zend也在设置用户登录时的PHPBB Cookie和会话,session_start使用它来查找会话ID:
if ($request->is_set($config['cookie_name'] . '_sid',\PHPbb\request\request_interface::COOKIE) || $request->is_set($config['cookie_name'] . '_u',\PHPbb\request\request_interface::COOKIE)) { $this->cookie_data['u'] = request_var($config['cookie_name'] . '_u',false,true); $this->cookie_data['k'] = request_var($config['cookie_name'] . '_k','',true); $this->session_id = request_var($config['cookie_name'] . '_sid',true); $SID = (defined('NEED_SID')) ? '?sid=' . $this->session_id : '?sid='; $_SID = (defined('NEED_SID')) ? $this->session_id : ''; if (empty($this->session_id)) { $this->session_id = $_SID = request_var('sid',''); $SID = '?sid=' . $this->session_id; $this->cookie_data = array('u' => 0,'k' => ''); } } else { $this->session_id = $_SID = request_var('sid',''); $SID = '?sid=' . $this->session_id; }
谢谢.