Event dispatch in Magento before redirect - php

I'm running into an issue when using event dispatch in Magento.
I'm using controller_action_predispatch to set a frontend session variable from a parameter in the URL.
Now, the issue seems like, when the user comes to the site initially, they might lend on a page that will redirect them to base URL (such a example.com to www.example.com).
But for some reason, after redirect, the session variable is lost...
Any ideas?
Thank you.
EDIT:
adding the code used:
public function grabRef($observer) {
$ref = Mage::app()->getRequest()->getParam('ref', $default);
if (isset($ref) && !is_null($ref) and !empty($ref)) {
Mage::getSingleton('core/session',array('name'=>'frontend'))->setRefid($ref);
}
}

There are only two remotely useful events dispatched prior to this redirection, but they are not specific to the redirect:
controller_front_init_before
controller_front_init_routers
The redirect depends on the "Auto-redirect to Base URL" setting from System > Configuration > Web > Url Options, which is evaluated by Mage_Core_Controller_Varien_Front->_checkBaseUrl(). This redirect occurs before any dispatching takes place, and it does not append GET or POST data, hence the loss of the param you are trying to capture.
Normally sessions are initialized under adminhtml or frontend session namespace based on the controller class being used (ref the action controller superclass method Mage_Core_Controller_Varien_Action->preDispatch(). You should be able to move your observer configuration under global/events/controller_front_init_before. Note that you must do this in the global event area, as the frontend event configuration part does not load until after this event is dispatched. That particular scenario cost me an hour once!

Related

Phalcon dispatcher forwarding having no effect

I have a component configured as a beforeDispatch listener. This component checks if a form was POSTed, then checks that the CSRF token was properly sent. If not, it's supposed to forward to a special CSRF notification page. I specifically want to do a forward and not a redirect, so that users have the option of reporting which page they visited.
Here is my code:
public function beforeDispatch(\Phalcon\Events\Event $Event,\Phalcon\Mvc\Dispatcher $Dispatcher){
if($this->request->isPost()){
if(!$this->checkToken()){
echo 'before';
$Dispatcher->forward(['controller'=>'index','action'=>'csrf']);
echo 'after';
exit();
}
}
}
All I get is a page that displays "beforeafter". If I take those echos out, I just get a blank page. I can visit /index/csrf/ manually and it displays the page I want.
Why is the request not getting forwarded? Is this out of the dispatch loop?
You have coded:
exit();
?
I'm not sure you can use forward here has the dispatcher does not yet know if the controller and action exist yet in the dispatch loop. https://docs.phalconphp.com/en/3.2/dispatcher#dispatch-loop
But I think you can intercept and control what the controller class and action the dispatcher should execute using.
$dispatcher->setModuleName(<your module nam if you have one>);
$dispatcher->setNamespaceName(<your controller class>);
$dispatcher->setActionName(<your action name>);
Check the docs on dispatch loop

Zend Framework 2 - Check for authentication in abstract controller -> onDispatch?

I am re-writing the authentication process for my application running under ZF2.
I need to have more options to authenticate the user depending on the service called.
I.E. for web application accessed from browser I will authenticate via Ldap and for API services I will check the user credentials in the header.
I created an abstract controller checking if the user is authenticated; if not it will be redirected to login page.
All the controllers in the modules needing the same authentication process will extend this class.
I need to save the original request to redirect it back to it after successful login.
My questions are:
1. Is the abstract controller -> onDispatch() method the right
place to place it?
Every solution I found around was always doing it in the Module.php. To distinguish the auth method they need to check if the requested controller match, since Module.php is called always. Isn't it 'cleaner' to set it in the controller?
2. Should I use redirect or forward to pass from original controller
to login controller and then back?
I don't mind the url changing in the browser bar, just looking for the best and fastest solution keeping also original request.
3. Is it correct to store the uri in the session class ( from the
auth module)? Is there any way to conserve the whole request (including maybe the POST data in case needed)?
Here is the abstract controller:
abstract class AbstractAuthActionController extends AbstractActionController {
public function onDispatch(MvcEvent $e) {
$serviceManager = $e->getApplication ()->getServiceManager ();
$auth = $serviceManager->get ( 'LdapAuth\Client\Ldap' );
if (! $auth->hasIdentity ()) {
$uri = $e->getRequest()->getRequestUri();
$callBackFunction = $this->getLdap ()->getCallBackFunction (); // = new SessionData();
$callBackFunction::setOriginalUri($uri); // function to store temporarly the uri
return $this->redirect ()->toRoute ( 'ldap-login-route' );
} else {
return parent::onDispatch ( $e );
}
}
}
A lot of people do that because they want to take care of checking authentication before the controller dispatch event. Authentication can be checked much earlier in the process, for example on route event, or at least before the controller has been instantiated (dispatch with higher priority then controller).
In case the user is unauthenticated you want to respond with a 401 (unauthorized) or 403 (forbidden) or a 302 (moved temporarily) response (read some more background on this status code here on Wiki) as early as possible to prevent all the overhead which only keeps your server (unnecessarily) occupied and thus slows down your application and delays the unauthenticated response.
module.php is NOT the best place to add all the authentication related code. Better would be to create an authentication listener (and inject a authentication service in the listener) and only connect the listener in your module.php.
Read on the difference between redirect and forward here in this answer. If want to redirect the client that it is not properly authenticated in a response with a 302 status code you will need to send a redirect response including this status code. I also see people using forward in such cases, but in my opinion it is not correct, because the client won't get notified about any redirection. You could also check authentication modules like ZfcUser to see how they handle this.
You don't need to store this url on the server, you can send the url you want to go to after logging in (the original url) inside the redirect response. For example you redirect to login.php from a request targeted at profile.php, then your redirect url could look like this:
http://www.example.com/login.php?redirect=profile.php
You can now set the redirect inside the login process/controller so that after a successful login you return the client to to profile.php.

Incorrect routing via /config/routes.php

I have the following (basic) route set up in a CI-based web app:
$route['sms/resend/(:num)/(:any)'] = 'sms/resend/$1/$2';
The controller + 'resend' method:
class Sms extends CI_Controller {
public function resend($to, $message) {
// my code
}
}
Logically speaking, anything that doesn't fit the route should be directed to a 404 page instead of the resend() method within the sms controller. This isn't the case, however. The following URL, for example, isn't redirected correctly, it goes to the same controller+method:
http://myapp/sms/resend/uuuu/WhateverMessage
What could be the problem?
After a bit of digging, I've come to understand that CI's default routing does not get deactivated when a default route related to a specific controller/method pair is added. That being said, if a URL does not fit the route $route['sms/resend/(:num)/(:any)'] = 'sms/resend/$1/$2', then the same URL is run through CI's default routing mechanism as a fallback, so it still takes me to the resend method of the sms controller. To prevent this from happening, I needed to add another custom route that follows all others related to the sms resending, that redirects any other url to a different controller+method. If this controller doesn't exist, you get the default 404 page.
So the final /config/routes.php file:
$route['sms/resend/(:num)/(:any)'] = 'sms/resend/$1/$2';
$route['sms/checkoperator/(:num)'] = 'sms/checkoperator/$1';
$route['sms/(:any)'] = 'somewhereovertherainbow';
I think the rout file is just for rerouting. Your URL don't fits the routing Conditions so it don't gets rerouted! So it goes the normal way wich is the same (in this case!)
Something like this could work!
(! :num) /(:any) '] = error page (or not existing page)
So every request wich doesn't start with a number gets redirected to the error page!
The syntax might be wrong!
This would work great :
$route['sms/resend/[^0-9]/(:any)'] = 'errorpage';
You have to replace the error page by something ;)

what the diffence beetween forward and redirect or setRenderView in Zend framework? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is the difference between redirect and forward in Zend framework
I'm new to zend framework, when i try to use foward, redirect, setViewRender in controller, what are their diffences?
As the official docs say:
_forward($action, $controller = null, $module = null, array $params = null): perform another action. If called in preDispatch(), the
currently requested action will be skipped in favor of the new one.
Otherwise, after the current action is processed, the action
requested in _forward() will be executed.
_redirect($url, array $options = array()): redirect to another location. This method takes a URL and an optional set of options. By
default, it performs an HTTP 302 redirect.
Read more to understand it better.
i'm pretty sure that a redirect redirects you to a particular page/ controller therefore going through all of the pre view processes including if you can view the page, setViewRender will just output the view you have selected and disregard all of the stuff the controller etc handles. (i haven't used zend for a while however)
_redirect creates a completely new http request, where as _forward simply forwards the request. I realized this when setting a variable in zend_registry, well this might sound a little off the track but when you use _request all the request variables and headers and registry variables are completely reset where as in case of _forward it simply forwards all those things. This is like you can have previously provided information along with some more information in case of _forward.
Well for setViewRenderer I really like this idea, I mean this is something like dependency injection. You dont really need to have a default view, you could provide a new view for the given action. I think you would get the best answer if you look into this.
_forward is an internal redirect. Where as _redirect sends a header that tells the client's browser to go to some other URL, _forward tells the Dispatcher to internally redirect the request somewhere else.
If you consider the normal dispatch order of:
preDispatch()
someAction()
anotherAction()
postDispatch()
Calling _forward at any point in that progression will cause the following steps to not be executed. So if you call _forward in preDispatch(), someAction() will not be called and so on. If you _forward() in someAction() and you are using the viewRenderer action helper to render your views (you are letting the framework choose what view script to render), then no view script will be rendered in someAction().
When the request is forwarded to the new Controller / Module the entire dispatch process will be repeated there.
Note:
If you forward inside someAction() to anotherAction() you must do it like this
return $this->_forward('another');
You should add a return to $this->_forward() or your current Action will continue to execute before forwarding to the other Action.
Also note that the view that will be rendered will be another.phtml
While when doing a redirect, ZF would instruct the browser to load http://example.com/controller-name/action-name as _redirect() sends a header, meaning you create a new HTTP Request and go through the entire dispatch process with it.
Last to render a certain view inside an action use the viewRenderer Action helper:
// Bar controller class, foo module:
class Foo_BarController extends Zend_Controller_Action
{
public function addAction()
{
// Render 'bar/form.phtml' instead of 'bar/add.phtml'
$this->_helper->viewRenderer('form');
}
public function editAction()
{
// Render 'bar/form.phtml' instead of 'bar/edit.phtml'
$this->_helper->viewRenderer->setScriptAction('form');
}
public function processAction()
{
// do some validation...
if (!$valid) {
// Render 'bar/form.phtml' instead of 'bar/process.phtml'
$this->_helper->viewRenderer->setRender('form');
return;
}
// otherwise continue processing...
}
}

Issue on zend dispatch loop

I'm using Zend Framework to build a website and I'm having some trouble with the dispatch loop.
Normally, Zend Framework URLs are built this way: http://www.domain.com/module/controller/action.
On my website, I'm using customized dynamic URLs which are parsed on the dispatch loop by a custom method. So, each one of these URLs, after being parsed, will execute a specific action of a specific controller and module.
I need to perform some tasks which depend on the module, controller and action that were parsed. The problem is that I'm only being able to know the parsed module, controller and action when dispatchLoopShutdown occurs. The tasks that I need to execute will set some cookies which will make changes on the output that will be sent to the browser.
But, at this point, the view has already been rendered, and the cookies that were set when dispatchLoopShutdown occurs won't change the output accordingly.
So, my question is... is there a way to force the view to be rendered again? Or a way to know what module, controller and action will be executed, before the dispatchLoopShutdown? I've also tried to accomplish this on the postDispatch but the results are the same!
Hope I could explain my problem right.
Thank you for your help.
Here is a good schema about the Zend Framework sequence.
You can know the module, controller and action before the dispatch by using a controller plugin:
<?php
class Custom_Controller_Plugin_CheckRoute extends Zend_Controller_Plugin_Abstract
{
public function preDispatch($request)
{
//Get Request
$controller = $request->controller;
$action = $request->action;
$module = $request->module;
//=> perform actions before dispatch
//Update the Request
$request->setModuleName('default')
->setControllerName('index')
->setActionName('action2');
}
}
?>
I had the same problem. It was solved by Zend_Controller_Plugin_ActionStack. I added some action where implemented logic from dispatchLoopShutdown. This link can be useful http://framework.zend.com/manual/1.12/en/zend.controller.plugins.html#zend.controller.plugins.standard.actionstack

Categories