zend session getting reset when user toggles between pages - zend-framework

I am learning Zend Framework and having issues with Zend_Session_Namespace.
Here is the scenario:
Homepage(user clicks on login-Index Controller)
login page(user auth is done->Login Controller)
On Successful login: Create a new zend_Session_Namespace("login") and take him to another page with home page button.
User Clicks the Home Page Button.I can Access the username from the session and display the welcome message.
User again clicks on the login page. I am checking isset($session->name) to prevent login again and take him to other page instead. --> I am failing here . The session is somehow reset , I am quite unsure what I am missing.
class IndexController extends Zend_Controller_Action
{
public function init()
{
}
public function indexAction()
{
$session = new Zend_Session_Namespace("login_session");
//Check if the session is already valid
if(isset($session->name)) {
$this->view->userLoggedIn="true";
$this->view->name=$session->name;
}
}
}
class LoginController extends Zend_Controller_Action
{
public function loginaction(){
$session = new Zend_Session_Namespace("login_session");
if(isset($session->name)){
//Redirect to New Page-Already Logged In
} else {
//Authenticate the user and if login is successful
$session->name="USER_NAME";
}
}
}
Thank You.

This code looks ok except for the previously mentioned typo.
It's possible and likely that somewhere else in your code you inadvertently overwrite the session namespace. I think we've all done that at least once.
I would suggest that instead of trying to roll your own authentication solution, use the one that ZF provides: Zend_Auth
a basic Zend_Auth login/logout might look like:
//non production code for example only
public function loginAction()
{
$form = new Application_Form_Login();
if ($this->getRequest()->isPost()) {
if ($form->isValid($this->getRequest()->getPost())) {
$data = $form->getValues();
$authAdapter = new My_Auth_Adapter($data['username'], $data['password']);
//authenticate
$result = $authAdapter->authenticate();
if ($result->isValid()) {
//store the user object
$auth = Zend_Auth::getInstance();
//access Zend_Auth session namespace
$storage = $auth->getStorage();
$storage->write($authAdapter->getUser());
//add message to flashmessenger
$this->message->addMessage('Welcome');
//redirect to the homepage
return $this->_redirect('/');
} else {
//handle authentication errors
$this->view->loginMessage =
"Sorry, your username or password was incorrect";
}
} else {
//handle form validation errors
$this->_redirect('/users/index/register');
}
} else {
//if not post render empty form
$this->view->form = $form;
}
}
public function logoutAction()
{
$authAdapter = Zend_Auth::getInstance();
$authAdapter->clearIdentity();
}
http://www.ens.ro/2012/03/20/zend-authentication-and-authorization-tutorial-with-zend_auth-and-zend_acl/
Good Luck!

Related

Show hide login/logout in Zend2 if user is logged in

How can i show or hide login/logout link if user is loged in. Should this be done directly in view?
In my onDispatch i see that it is using $this->getAdminAuthService()->hasIdentity() to check if user is loged in.
How to use it in view like this?
if($this->getAdminAuthService()->hasIdentity()){
echo "login";
}
else {
echo "Logout"
}
Try this in your controller:
public function onDispatch(\Zend\Mvc\MvcEvent $e)
{
$header = new ViewModel(array('login'=>$this->getAdminAuthService()->hasIdentity()));
$header->setTemplate('layout/header');
$this->layout()->addChild($header, 'header');
}
then :
//layout/header.phtml
if($this->login){
echo "login";
} else {
echo "Logout"
}
A view helper might be a more self contained solution for this
namespace MyModule\View\Helper;
use Zend\View\Helper\AbstractHelper;
use MyModule\Service\AuthService;
class IsAuthenticated extends AbstractHelper
{
protected $authService;
public function __construct(AuthService $authService) {
$this->authService = $authService;
}
public function __invoke()
{
return $this->authService->hasIdentity();
}
}
Create a factory in your module.php
public function getViewHelperConfig()
{
return array(
'factories' => array(
'IsAuthenticated' => factory($sl) {
$authService = $sl->getServiceLocator()->get('AuthService');
return new View\Helper\IsAuthenticated($authService);
},
),
);
}
Then you can use this within the view or layout - perhaps with a view partial
if ($this->isAuthenticated()) {
// render the login/logout
$this->partial('some/view/file', array('foo', 'bar'));
}
The plugin could be expanded to proxy to other AuthService methods. However I hope this brief example shows how to go about it.
I don't know what version of ZF2 you're using, but 2.2.x ships with a view helper for checking a user's identity from the AuthenticationService out of the box.
$this->identity();
View Helper - Identity

Pass a form with post method to another controller

I have a simple Zend Form that contains a textbox with setRequired(TRUE) and other validators and a simple submit button in IndexController.
My question is, is it possible another controller will process and validate my post form?
Login.php
<?php
class Application_Form_Login extends Zend_Form
{
public function init()
{
$username = $this->createElement('text', 'username');
$username->setLabel('Username:');
$username->setRequired(TRUE);
$username->addValidator(new Zend_Validate_StringLength(array('min' => 3, 'max' => 10)));
$username->addFilters(array(
new Zend_Filter_StringTrim(),
new Zend_Filter_StringToLower()
)
);
$this->addElement($username);
// create submit button
$this->addElement('submit', 'login',
array('required' => false,
'ignore' => true,
'label' => 'Login'));
}}
IndexController.php
<?php
class AttendantController extends Zend_Controller_Action
{
public function indexAction()
{
$loginForm = new Application_Form_Login();
$loginForm->setAction('/Auth/process');
$loginForm->setMethod('post');
$this->view->loginForm = $loginForm;
}
}
AuthController.php
class AuthController extends Zend_Controller_Action
{
public function processAction()
{
// How to validate the form posted here in this action function?
// I have this simple code but I'm stacked here validating the form
// Get the request
$request = $this->getRequest();
// Create a login form
$loginForm = new Application_Form_Login();
// Checks the request if it is a POST action
if($request->isPost()) {
$loginForm->populate($request->getPost());
// This is where I don't know how validate the posted form
if($loginForm->isValid($_POST)) {
// codes here
}
}
}
}
You're pretty close. In the process action you create a new instance of the login form (which you are doing), and you pass the POST data to the isValid() method of that form in order to validate. So:
public function processAction()
{
$request = $this->getRequest();
$loginForm = new Application_Form_Login();
if($request->isPost()) {
if($loginForm->isValid($request->getPost)) {
// codes here
} else {
// assign the login form back to the view so errors can be displayed
$this->view->loginForm = $loginForm;
}
}
}
Generally it is easier to display and process the form within the same action, and redirect when the submission is successful. This is the Post/Redirect/Get pattern - see http://en.wikipedia.org/wiki/Post/Redirect/Get. This saves you having to create an instance of the same form in two different actions and makes it easier to redisplay the form in case of errors.
Are you using ' ?
change $loginForm->setAction(/Auth/process); to $loginForm->setAction('/auth/process');
from processAction you may remove $login->populate($request->getPost());

CakePHP and Facebook with Security Component turned on

I want the Security Component turned on.
BUT when you load a CakePHP app inside a Facebook tab, FB posts $_REQUEST['signed_request'] to my form - the problem with this is that the Security Component "reacts" to this "post" and gives me validation errors, black-hole, etc.
How do I go around this?
I could not find anything on the documentation to go around this problem.
What I wanted was to somehow run the Security Component "manually" so that it only "reacts" when I actually submit my form and not when Facebook posts the $_REQUEST['signed_request'] to my form.
UPDATE:
<?php
App::uses('CakeEmail', 'Network/Email');
class PagesController extends AppController {
public $helpers = array('Html','Form');
public $components = array('RequestHandler');
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('*');
$this->Security->validatePost = true;
$this->Security->csrfCheck = true;
$this->Security->unlockedFields[] = 'signed_request';
}
public function home() {
$this->loadModel('Memberx');
if($this->request->is('post') && isset($this->request->data['Memberx']['name'])) {
//...save here, etc. ...
}
}
FYI: I get a "black hole" error.
FINAL UPDATE (After #tigrang's answer):
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('*');
$this->set('hasLiked', false);
if(isset($this->request->data['signed_request'])){
$this->set('hasLiked', $this->hasLiked($this->request->data['signed_request']));
}
if(isset($this->request->data['Memberx']['signed_request'])) {
$this->set('hasLiked', $this->hasLiked($this->request->data['Memberx']['signed_request']));
}
/*
To go around Facebook's post $_REQUEST['signed_request'],
we unset the $_REQUEST['signed_request'] and disable the csrfCheck
ONLY after we have set the hasLiked view variable
*/
unset($this->request->data['signed_request']);
if (empty($this->request->data)) {
$this->Security->csrfCheck = false;
}
}
Then, I do something like below in my views:
<?php
if($hasLiked) {
?>
You have liked this page!
<?php
}
?>
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('*');
$this->_validateFbRequest();
}
protected function _valdiateFbRequest() {
if (!isset($this->request->data['signed_request'])) {
// not a valid request from fb
// throw exception or handle however you want
return;
}
$signedRequest = $this->request->data['signed_request'];
unset($this->request->data['signed_request']);
if (empty($this->request->data)) {
$this->Security->csrfCheck = false;
}
// validate the request
}

Codeigniter facebook login

I'm trying to use the code from this Tutorial: http://www.betterhelpworld.com/codeigniter/how-to-use-facebook-php-sdk-v-3-0-0-with-codeigniter to do login via facebook: My controller code looks like:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class User extends CI_Controller {
public function __construct()
{
parent::__construct();
}
function index() {
$this->loginByFacebook();
}
function facebook() {
$this->load->library('fb_connect');
if (!$this->fb_connect->user_id) {
echo 'not ok';
}
else
{
$fb_uid = $this->fb_connect->user_id;
$fb_usr = $this->fb_connect->user;
print_r($fb_usr); // Printing to show all available variables
// Do your processing here after login. May be you can check if first time user then can register in your database.
echo 'ok';
}
}
function loginByFacebook() {
$this->load->library('fb_connect');
$param['redirect_uri'] = site_url("user/facebook");
$param['scope'] = 'email, publish_stream,user_birthday,offline_access'; // Set the required access here
redirect($this->fb_connect->getLoginUrl($param));
}
}
After calling the login I'll be redirected to facebook, asked for permissions and redirected to my application but then I get always the not ok message string which means, that the user is not connected. So what am I doing wrong?

logout facebook connect session

I'm trying to integrate my site with facebook connection to handle facebook signup and facebook login. i'm using codeigniter framework. But I got this problem now:
current facebook login user is "test1". I go to my site to sign up with facebook, everything works fine and "test1"'s info are stored in my database. However, after I log test1 out from facebook, and login "test2" in on facebook, I go back to my site and do a signup with facebook again, it still "test1"'s info stored.
I use ion auth library to handle user logout from my site. However, after I switch facebook test user accounts and do a "login with facebook" again, it still get the previous facebook user.
Based on the 2 cases above, it seems that the facebook session wasn't cleared up? I'm struggling on this problem for a long time, please help!
I user this to get user data:
$fb_usr = $this->fb_connect->user;
(it seems that no matter how the facebook user changs, fb_connect always return same user)
and fb_connect is sth like this:
<?php
include(APPPATH.'libraries/facebook/facebook.php');
class Fb_connect extends Facebook{
//declare public variables
public $user = NULL;
public $user_id = FALSE;
public $fbLoginURL = "";
public $fbLogoutURL = "";
public $fb = FALSE;
public $fbSession = FALSE;
public $appkey = 0;
//constructor method.
public function __construct()
{
$CI = & get_instance();
$CI->config->load("facebook",TRUE);
$config = $CI->config->item('facebook');
parent::__construct($config);
$this->user_id = $this->getUser(); // New code
$me = null;
if ($this->user_id) {
try {
$me = $this->api('/me');
$this->user = $me;
} catch (FacebookApiException $e) {
error_log($e);
}
}
if ($me) {
$this->fbLogoutURL = $this->getLogoutUrl();
} else {
$this->fbLoginURL = $this->getLoginUrl();
}
} //end Fb_connect() function
}
I think what you need to do is set the "next" param for your getLogoutUrl() call. Something like this:
$args['next'] = site_url('logout'); // replace "logout" with your controller which will clear the session
$fbLogoutURL = $facebook->getLogoutUrl($args);
Then, in the controller set as "next" you'll need to clear the session data.
class Logout extends CI_Controller {
public function index() {
$facebook->destroySession();
$this->session->sess_destroy(); // Assuming you have session helper loaded
$this->load->view('logout');
}
}
Let me know if that helps.