Sessions in ZF2 - php

Could you tell me how to properly use sessions in ZF2? So far I have this code:
"session" =>
[
"remember_me_seconds" => 2419200,
"use_cookies" => true,
"cookie_httponly" => true
]
That's the session config I copied from some post here on stackoverflow. Now should I put this code into module.config.php in each module that uses sessions or in the Application module?
public function onBootstrap(EventInterface $Event)
{
$Config = $Event->getApplication()->getServiceManager()->get('Configuration');
$SessionConfig = new SessionConfig();
$SessionConfig->setOptions($Config['session']);
$SessionManager = new SessionManager($SessionConfig);
$SessionManager->start();
Container::setDefaultManager($SessionManager);
}
Same problem with the onBootstrap() method of the Module class. Should this code go into each module's Module class or just once into the Application's Module class?
In both cases I have tried both approaches and I even tried putting this code into both modules at once, but the only thing I was able to accomplish was to set session variables in controller's constructor and then read them in actions/methods. I wasn't able to set a session variable in one action/method and then read it in another. If I remove the lines in which I set the variables in controller's constructor, I can no longer see these variables in the session. The session just behaves like it was created and deleted each time a page is requested.
Am I missing something? Please don't link me to any resources on the internet, I have read them all and they're not really helpful.

You don't need to do any configuration to use sessions in Zend Framework 2. Sure, you can change settings, but if you just want to get up and running with sessions, then don't worry about it for now.
My apologies, but I am going to disregard your last sentence; about a month ago, I wrote an article about this subject with the purpose of showing how to quickly get started with using sessions in ZF2. It doesn't rank well in search engines, so chances are you haven't read it.
Here is a code snippet showing how it can be done. If you are interested in how it works behind the scenes, then please refer to the link above.
namespace MyApplication\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\Session\Container; // We need this when using sessions
class UserController extends AbstractActionController {
public function loginAction() {
// Store username in session
$userSession = new Container('user');
$userSession->username = 'Andy0708';
return $this->redirect()->toRoute('welcome');
}
public function welcomeAction() {
// Retrieve username from session
$userSession = new Container('user');
$username = $userSession->username; // $username now contains 'Andy0708'
}
}

about session
Where do you want to store session (in mysql-db, in mongo-db,or in ram,..)?
How to classify session into "namespace" like
$_SESSION["namespace"]["user"],
$_SESSION["namespace_1"]["user"]?
SessionManager
in Zend, Zend\Session\SessionManger help you to do many as what listed above
simple config for SessionManger
$sessionManager = new SessionManager();
$sessionStorage = new SessionArrayStorage();
$sessionManager->setStorage($sessionStorage);
//you can add more config, read document from Zend
$sessionContainer = new Container("ABC", $sessionManager);
$sessionContainer->offsetSet("user", "lehoanganh25991");
when you call new Container without any SessionManager config
$sessionContainer = new Container("abc");
behind the scence, Zend create a default SessionManager, then pass it into Container
SessionArrayStorage, $_SESSION
SessionArrayStorage in Zend can work with $_SESSION, we can access to user above through
$_SESSION["ABC"]["user"]
if you set other storages like mysql-db, mongo-db, in ram,..
access through $_SESSION may not work
access session
in Module A, set session
How can we access it in Moudle B? where $sessionContainer variable ##?
it quite weird, but when you want to access to the this container, create a new one with SAME CONFIG
$sessionManager = new SessionManager();
$sessionStorage = new SessionArrayStorage();
$sessionManager->setStorage($sessionStorage);
$sessionContainer = new Container("ABC", $sessionManager);
//access
var_dump("get user from \$sessionContainer", $sessionContainer->offsetGet("user"));
review demo on github: https://github.com/hoanganh25991/zend-auth-acl/tree/d0a501e73ac763d6ef503bbde325723ea1868351
(through commits, the project changed, access it at this tree)
in FronEnd\Controller\IndexController
in AuthAcl\Module.php
in AuthAcl\Service\SimpleAuth
i acces same session at different places

namespace Application\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Zend\Session\Container;
class IndexController extends AbstractActionController
{
// set session values
public function indexAction()
{
$session = new Container('User'); // name your session here by replacing User
$user_session->offsetSet('user_name', "your user name"); // set your session user name
$user_session->offsetSet('user_id', "1232"); //set your session user id
}
// function to get values from session
public function getdataAction(){
$session = new Container('User');
$user_name= $user_session->offsetGet('user_name'); // get user name from the session
$user_id= $user_session->offsetGet('user_id'); // get user id from the session
}
// function to unset session values
public function unsetdataAction(){
$session = new Container('User');
$user_session->offsetUnset('user_name'); // unset user name
$user_session->offsetUnset('user_id');
}
}

Related

Set variable before every controller

Notice beforehand: I can't use the security bundle because the database I use is also used by other applications which are built on a whole other role system.
I'm trying to set a variable to check if a user is logged in before each controller action. What I would like to do is check if it's logged in (by a session) and if that is the case load the entity corresponding to a query in my UserRepository.
I know this would normally be done via the Security Bundle of Symfony but since it requires you to implement the UserProviderInterface I can't use it at all, however if someone knows if you can write your own UserProviderInterface with a custom translation mapping for roles. That would be great too.
I hope I've been informative about my question.
TL;DR: Is there a way to set a variable before every controller action which can be accessed by the following controller.
I think you can use sessions:
use Symfony\Component\HttpFoundation\Request;
public function indexAction(Request $request)
{
$session = $request->getSession();
// store an attribute for reuse during a later user request
$session->set('foo', 'bar');
// get the attribute set by another controller in another request
$foobar = $session->get('foobar');
// use a default value if the attribute doesn't exist
$filters = $session->get('filters', array());
}
please check link http://symfony.com/doc/current/book/controller.html

Do I need to start the session at any controller where I need to access it?

I have this code in the indexAction of a controller and that index is a start point for a process (include call to several controllers through Ajax):
$session = $request->getSession();
$currentData = [];
$session->set('currentData', $currentData);
Now suppose that I need to set a new value for currentData in another controller, I'm doing right now as:
$session = $request->getSession();
// get currentData from session for not override the values
$currentData = $session->get('currentData');
// sets the new value
$currentData['newValue'] = 1;
// save the var again and override currentData session
$session->set('currentData', $currentData);
Regarding this and as title says the question is easy: Do I need to start (call $session = $request->getSession() all the time whenever I need access to session) the session at any controller where I need to access it? Exists any best way to achieve this or I'm the one did all wrong? Any advice?
NOTE: I forgot to mention I'm talking and working with Symfony 2.6.3
You don't have to, however it is recommended. From the docs:
While it is recommended to explicitly start a session, a session will actually start on demand, that is, if any session request is made to read/write session data.
You do need to get the Session container by using $session = $request->getSession(), $session = $this->get('session'), or $session = new Symfony\Component\HttpFoundation\Session\Session();. This is not the same as starting a session and there's really no difference between the three ways.
This applies to any Symfony 2.x version.

Is there any way to find out the current username from the Symfony2 AppKernel.php?

First off I don't care how this is solved, I would be happy with a solution at all.
I need to create an application that allows the users to dynamically activate/deactivate bundles.
To make it easier, and to save myself from a headache, I won't use
Doctrine, but save a file into the users directory
dir:/users/{username}/activated_bdls.ini and loop through the files
from the AppKernel.php to activate the bundles accordingly.
Its as easy as pushing the new directories into the bundles array depending on the configuration file:
$bundles[] = new Acme\Bundle\DemoBundle\DemoBundle();
At the moment the file that is looped through has a hard-coded path
dir:/users/{hardcoded_username}/activated_bdls.ini, which needs to be replaced with the current username.
I tried using this, doesn't work, but might give you an idea.
$current_username = new \Gabriel\LayoutBundle\Controller\profileController;
$current_username = $current_username->getCurrentUsernameAction();
The Appkernel gets loaded again everytime the user reloads the page,
So after the user logs in, set the current user session variable
// logincontroller
$_SESSION['username'] = $this->getUser()->getUsername();
//since the page gets reloaded on login, you can access it from the AppKernel
session_start();
if(isset($_SESSION['username']))
{
$username = $_SESSION['username'];
read_stuff_from = ':dir/'.$username.'/file'
for(loop_through_logic)
{
doStuff()
}
}
I won't set this question as best yet in case you come up with a less dirty solution
Certainly I can't see why you'd ever want the bundles different on a
per-request basis.
maybe to save headaches you can write the username when you are in Controller-scope (some index/landingpage or better at login_check) into a file e.g /users/currentuser
and in your AppKernel you could read this file, sth. like:
class AppKernel extends Kernel {
private $currentUser;
public function __construct($environment, $debug) {
parent::__construct($environment, $debug);
$this->currentUser = trim(file_get_contents(__DIR__ . '/../users/currentuser'));
}

Symfony Session Last Request Time

Is it possible to make an action (more specifically 'ajax/heartbeat') not update last request time for the session ?
It is used for fetching notifications etc, so it shouldn't update timeout on sessions or they will never expire.
If the user is doing stuff on the page (onmousemove) I set update=true else update=false
Well, you will have to hook into the User lib of Symfony.
lastRequest is updated during the initialization of the User lib (ie: inside sfBasicSecurityUser).
Inside your app/[appname]/lib/myUser.class.php, extends this initialize function to not set the request time. Something ugly like that:
public function initialize(sfEventDispatcher $dispatcher, sfStorage $storage, $options = array())
{
$lastRequest = $this->getLastRequestTime();
parent::initialize($dispatcher, $storage, $options);
if (condition)
{
$this->lastRequest = $lastRequest;
}
}
The only things you need to find is, how to catch the module/action from the myUser lib and then place it in condition.

How to get third-party app session data from a Symfony2 app?

In order to implement cross application authentication (getting logged in in my Symfony2 app if the user already logged in in an other application), I made a Symfony2 listener class that checks if specific data concerning the user is in the session. This data comes from a non-Symfony2 (but PHP) app.
The problem is that the session data from the other app is not present in the session object I use in my class.
Here is the listener (simplified) class:
<?php
class OldAppAuthenticationListener
{
/** #var \Symfony\Component\Security\Core\SecurityContext */
private $context;
public function __construct(SecurityContext $context)
{
$this->context = $context;
}
public function onKernelRequest(GetResponseEvent $event)
{
if (HttpKernel::MASTER_REQUEST != $event->getRequestType()) {
// don't do anything if it's not the master request
return;
}
if (!$this->context->isGranted('IS_AUTHENTICATED_FULLY')) {
$request = $event->getRequest();
$session = $request->getSession();
$userName = $session->get('nomUtilisateur');
$token = new PreAuthenticatedToken($userName, null, 'secured_area', array('ROLE_USER'));
$session->set('_security_secured_area', serialize($token));
}
}
}
It is registered in services.yml like this:
services:
my_app.listener.old_app_authentication:
class: Acme\MyAppBundle\Listener\MyAppAuthenticationListener
arguments: ["#security.context"]
tags:
- { name: kernel.event_listener, event: kernel.request }
But the $session->get('nomUtilisateur') always returns NULL (and $session->all() and $_SESSION only return some Symfony2 specific vars) although the other app stores all this data in the session.
Of course, I use the same cookie session domain for both apps (as configured in config.yml) and I can easily check that the PHPSESSID is the same.
So here is my question: why are the old app session variables not available and how can I get them from my listener class?
As stated here, Symfony2 uses session bags to store session stuff. This means that you have to directly access the $_SESSION superglobal for such a functionality.
For me the solution was to use directly the php session fonctions.
also I had to check if session name, domain and save path are the same on both applications.
In my symfony I had to add:
session_save_path('c:/wamp/tmp');
session_name(_SESSION_ID_);
session_start();
and then use $_SESSION
an other way that was given to me, but I didn't use is to use the sessions files directly like this:
"The trick was using the session cookie sent by the browser.
For example, an old web application, written in PHP, sent a cookie
called IntranetSession to the browser. As I knew where does PHP store
the session files, I simply opened that file, and decoded its contents
with session_decode(). The drawbacks of this is that session_decode()
puts its output directly into $_SESSION, overwriting you current
session data (even the stuff put there by Symfony). Basically the rule
is as follows:
$sessionData = file_get_contents($sessionFile);<br>
$tmpSess = $_SESSION;<br>
session_decode($sessionData);<br>
$otherAppSession = $_SESSION;<br>
$_SESSION = $tmpSess;<br>
"
hope this helps!

Categories