【发布时间】:2010-11-13 14:52:38
【问题描述】:
我正在尝试在 Joomla 之外运行应用程序(而不是作为插件),并且我想访问已登录用户的信息(用户 ID)。我想知道我应该怎么做呢?有我可以包含的文件吗?我尝试使用 $_SESSION 但它显示为空。
我的问题有简单的解决方案吗?感谢您的宝贵时间。
【问题讨论】:
我正在尝试在 Joomla 之外运行应用程序(而不是作为插件),并且我想访问已登录用户的信息(用户 ID)。我想知道我应该怎么做呢?有我可以包含的文件吗?我尝试使用 $_SESSION 但它显示为空。
我的问题有简单的解决方案吗?感谢您的宝贵时间。
【问题讨论】:
实际上,这并不像听起来那么容易。 Joomla 使用自己的会话处理,带有独特的会话 ID 生成和一些加密,因此进入 Joomla 会话数据的唯一方法是使用适当的 Joomla 功能(正如其他人所建议的那样)。我最近有一个项目,我们需要将经过 Joomla 身份验证的用户转移到单独的应用程序中。我们通过添加一个 Joomla 适配器来实现这一点,该适配器实例化 Joomla 用户类、读取用户数据、将所有内容放入加密的 cookie 并重定向回我们的应用程序。在那里,我们读取加密的 cookie,实例化我们自己的用户对象并丢弃 cookie。由于这不是 100% 安全的,我们正在更改系统以将用户数据写入数据库表并从我们的应用程序中读取 - 我们通过这种方式避免了通过 cookie 的不安全方式,因为即使 cookie 是加密的(并且包含足以验证用户身份的敏感用户信息)将通过网络传输并可能被嗅探。
define( '_JEXEC', 1 );
define('JPATH_BASE', dirname(dirname(__FILE__)));
define( 'DS', DIRECTORY_SEPARATOR );
require_once (JPATH_BASE . DS . 'includes' . DS . 'defines.php');
require_once (JPATH_BASE . DS . 'includes' . DS . 'framework.php');
$mainframe = JFactory::getApplication('site');
以上是访问Joomla资源所需的基本脚本。
【讨论】:
JPATH_BASE 常量调整为可以找到 Joomla 安装的路径即可。
define( '_JEXEC', 1 );
define('JPATH_BASE', 'your joomla basedir goes here' );
define( 'DS', DIRECTORY_SEPARATOR );
require_once ( JPATH_BASE .DS.'includes'.DS.'defines.php' );
require_once ( JPATH_BASE .DS.'includes'.DS.'framework.php' );
JDEBUG ? $_PROFILER->mark( 'afterLoad' ) : null;
$mainframe =& JFactory::getApplication('site');
$mainframe->initialise();
JPluginHelper::importPlugin('system');
JDEBUG ? $_PROFILER->mark('afterInitialise') : null;
$mainframe->triggerEvent('onAfterInitialise');
$user =& JFactory::getUser();
if ($user->guest) {
echo 'stuff';
//redirect('/');
} else {
echo 'user';
}
【讨论】:
解决方案是为您的整个域和/或站点设置会话。如果您尝试访问 joomla 范围之外的会话数据,它适用。例如,如果您的 joomla 站点位于 http://example.com/joomla/ 而您的其他站点位于 http://othersite.example.com/ 上,则保存会话 id 的 cookie 不会从 joomla 传输到其他站点。要修改此行为,请在每个 session_start() 之前使用 session_set_cookie_params (我不太了解 joomla,但您应该只添加几行代码)。以这种方式使用它:
session_set_cookie_params(86400, '/', '.example.com');
86400 是会话的生命周期,将其设置为您喜欢的值(86400 是一天)。 '/' 是 cookie 的路径。这意味着如果您的 joomla 站点位于 http://example.com/joomla/ ,如果用户访问 http://example.com/ ,会话 cookie 仍然会发送。
'.example.com' 是域。注意开头的点,它非常重要。它表示会话 cookie 将在 example.com 的任何子域上发送。不放的话,cookie只会发送给http://example.com/开头的地址。
这应该可以解决您的问题,除非您尝试从另一个域访问会话数据。如果是这样,请在这里发表评论,我会看看我是否能找到一些东西。
【讨论】:
Stefan Gehrig
展示的解决方案define( '_JEXEC', 1 );
define('JPATH_BASE', dirname(dirname(__FILE__)));
define( 'DS', DIRECTORY_SEPARATOR );
require_once (JPATH_BASE . DS . 'includes' . DS . 'defines.php');
require_once (JPATH_BASE . DS . 'includes' . DS . 'framework.php');
$mainframe = JFactory::getApplication('site');
工作正常,我花了很多个漫长的夜晚尝试访问 Joomla! joomla 文件夹外的资源。
$session = &JFactory::getSession();
在后续代码中,当 getApplication 方法被调用时可以正常工作。
感谢您的解决方案。
【讨论】:
首先你必须为一些joomla的常量(标识符)提供如下定义:
define( '_JEXEC', 1 );
define( 'DS', DIRECTORY_SEPARATOR );
define( 'JPATH_BASE',$_SERVER['DOCUMENT_ROOT'].DS. basename(dirname(__DIR__)) );
其中:JPATH_BASE 代表您站点的根目录。一定是对的。
在than之后,您必须使用以下密钥文件:
require_once ( JPATH_BASE .DS.'includes'.DS.'defines.php' );
require_once ( JPATH_BASE .DS.'includes'.DS.'framework.php' );
之后,您必须创建一个应用程序对象并对其进行初始化:
$mainframe =& JFactory::getApplication('site');
$mainframe->initialise();
[这是可选的]如果你想导入一些其他的库,那么你可以这样做:
jimport( 'joomla.user.user');
jimport( 'joomla.session.session');
jimport( 'joomla.user.authentication');
所以你的文件的核心代码如下:
define( '_JEXEC', 1 );
define( 'DS', DIRECTORY_SEPARATOR );
define( 'JPATH_BASE',$_SERVER['DOCUMENT_ROOT'].DS. basename(dirname(__DIR__)) );
require_once ( JPATH_BASE .DS.'includes'.DS.'defines.php' );
require_once ( JPATH_BASE .DS.'includes'.DS.'framework.php' );
$mainframe =& JFactory::getApplication('site');
$mainframe->initialise();
//optional use depend on requirement
jimport( 'joomla.user.user');
jimport( 'joomla.session.session');
jimport( 'joomla.user.authentication');
【讨论】:
要获取用户 ID,您需要使用 Joomlas 函数:
$user =& JFactory::getUser();$user->get('id');
会让你得到用户ID。但是,您需要在 joomla 页面中执行此操作,所以我不知道这顶帽子对您有多大用处。
【讨论】:
在mod_login.php应用这个
之后:
$user =& JFactory::getUser();
echo "<p>Your usertype is {$user->usertype} which has a group id of {$user->gid}.</p>";
【讨论】:
Joomla 很可能像 Wordpress 一样不使用任何“会话”数据,而是直接从数据库中提取数据。在这种情况下,您需要使用 Joomla 的原生函数。
但这只是我使用 Wordpress 的经验。
更新
我想我错了。
假设这是访问 Joomla Session 变量的 api 类:
// 返回对全局的引用 JSession 对象,仅在以下情况下创建它 它尚不存在 $session = &JFactory::getSession();
// 从会话变量中获取一个值 $value = $session->get('var_name', 空);
// 将值放入会话 var $session->set('var_name', $value);
【讨论】:
了解在 jFusion 等应用程序桥中如何实现这一点可能会有所帮助。我建议至少为 Joomla 提供一个系统插件,它将使用 joomla 功能从 joomla 安装中获取您需要的一切,并在应用程序初始化时发送到您的应用程序。最重要的问题将是你的数据流建模!
【讨论】:
要获取 Joomla 用户 ID,请使用:
$user =& JFactory::getUser();
$user_id = $user->get('id');
并获取用户会话 ID 使用:
$session = & JFactory::getSession();
$session_id = $session->getId();
【讨论】:
如果您将会话存储在数据库中,您可以按照以下评论解码会话数据:
http://www.php.net/manual/en/function.session-decode.php#79244
【讨论】:
我假设您所说的应用程序是指另一个网站。您最好的选择是在该应用程序中使用 iframe 来实例化 Joomla 启动文件,在该 iframe 中获取用户 ID,将其与您当前的会话 ID 一起存储在数据库中的某个位置,然后由其他应用程序检索它。不过需要一些时间。
【讨论】:
我将下面的代码放在 Joomla index.php 中,它对我来说很好。
//Set session to access it outside
$user =& JFactory::getUser();
$username = $user->get('username');
session_start();
$_SESSION['username'] = $username;
现在您可以在 Joomla 之外使用会话变量,如下所示
session_start();
$_SESSION['username'];
【讨论】:
我不能告诉你 Joomla 版本高于 1.5 是如何做到这一点的,但在 Joomla 1.5 中你是如何做到这一点的:(我相信其他版本的程序非常类似)
Joomla 为网站的前端和后端生成唯一的会话 ID。 要访问会话数据,您只需要知道会话 ID。
在joomla配置文件中有一个参数叫“secret”
对于后端,这是生成会话 ID 的方式:
$session_id = md5( md5( JConfig::$secret.'administrator' ) );
对于前端:
$session_id = md5( md5( JConfig::$secret.'site' ) );
之后是一个简单的查询
mysql_query( 'SELECT `data` FROM jos_session WHERE session_id="'.$sessionId.'" )
将使您能够访问会话数据。您所需要的只是解密它 session_decode 会话数据将在 $_SESSION 变量中。
不要忘记把session_start放在session_decode之前,否则它不起作用
【讨论】:
Joomla 3 的解决方案,不使用任何库。
require_once '../configuration.php'; // load Joomla configuration file
$jConfig = new \JConfig();
$secret = $jConfig->secret;
$dbprefix = $jConfig->dbprefix;
$cookieName = md5(md5($secret . 'site'));
$sessionId = $_COOKIE[$cookieName];
$sql = "select userid from {$dbprefix}session where client_id = 0 and session_id = ?";
$userId = $db->lookup($sql, [$sessionId]);
(上面的代码是简化的,没有任何错误处理。)
【讨论】: