I wondering how to perform an access control in a entire module. Let me explain : If I have got a module (/authentication/) which is only developed to create a session. And a another module (/Main/) which contains the main application.
What I want to do is to check in any request on the main module if a session was correctly created by a user.
During my research on the internet, I saw a method to do it. I'm not sure, so tell me if my solution is good : I will implemente an event in my bootstrap function (on module.php) which will check if the session is correctly created. If it is not I will redirect to the module authentication.
public function onBootstrap($e){
$eventManager = $e->getApplication()->getEventManager();
$auth = new AuthenticationService();
if (!$auth->hasIdentity()) {
$response = $e->getResponse();
$response->getHeaders()->addHeaderLine('Location', 'authentification');
$response->setStatusCode(302);
}
$moduleRouteListener = new ModuleRouteListener();
$moduleRouteListener->attach($eventManager);
}
What do you think about this solution ?
Unfortunately this solution is not good.
I don't know why, but it seem that this code is executed even in the module authentication.
So at the first call when you are trying to go in the url : /main, you will be redirect to the module /authentication and again the code will be re-executed and the module will redirect you to /authentication and again and again and again...
So I think the solution is to check if the requested url is different from this one /authentication.
How to do this ?
Hope my question is clear and easily understandable.
Thank you =D
public function onBootstrap(MvcEvent $e) {
$eventManager = $e->getApplication()->getEventManager();
$eventManager->attach(MvcEvent::EVENT_DISPATCH, function($e) {
$controller = $e->getTarget();
$auth = new AuthenticationService();
$is_login = $auth->hasIdentity();
//check if action is login
$params = $e->getApplication()->getMvcEvent()->getRouteMatch()->getParams();
if ($params['action'] == 'login') {
if ($is_login) {
return $controller->redirect()->toRoute('adminindex');
}
} else {
if (!$is_login) {
return $controller->redirect()->toRoute('adminauthlogin');
}
}
});
}
a little bit better solution ;)
Related
My opencart front-end works well, while back-end /admin returns me blank page.
I debugged my /admin/index.php and find after
$controller->dispatch($action, new Action('error/not_found'));
the program stopped. So I won't be able to see even the echo.
Here is the code:
Back-end admin/index.php
// Router
if (isset($request->get['route'])) {
$action = new Action($request->get['route']);
} else {
$action = new Action('common/home');
}
// Dispatch
var_dump($action);
$controller->dispatch($action, new Action('error/not_found'));
echo "second+++++++++++++++++++++++++++++++++";
var_dump($response);
// Output
$response->output();
By the way the frond end works well, as it returned me echo and $response value after dispatch:
if (isset($request->get['route'])) {
$action = new Action($request->get['route']);
} else {
$action = new Action($config->get('config_default_controller'));
}
// Dispatch
var_dump($action);
$controller->dispatch($action, new Action($config->get('config_default_controller_error')));
echo "second++++++++++++++++++++++++++";
var_dump($response);
I have checked the $action and $controller they are all with good values and paths.
Do anyone know what happened here with dispatch ? or give me any information about dispatch and why the program stop. Thank you in advance.
after few hours i found solution.
In my case it was wrong config. I had same issue and after checking what is wrong i figure out that my paths in config.php file in admin folder was with wrong values.
Opencart have two cfg files.
Next thing what i changed was config_url in database. Hope it will help you.
After a user fails authorisation I'd like to forward them back to the login page. Currently the _forward method causes Zend to hang and give a time out error (30 seconds exceeded).
The code for the login page handles both a login and signup form, and forwards to the authorisation controller:
public function indexAction() {
if ($this->_request->isPost()) {
$formData = $this->_request->getPost();
if (array_key_exists('signUp', $formData)) {
$authAction = 'signup';
$form = 'signupForm';
} elseif (array_key_exists('logIn', $formData)) {
$authAction = 'login';
$form = 'loginForm';
}
if ($this->$form->isValid($formData)) {
$this->_forward($authAction, 'user-auth', null, $formData);
} else {
$this->$form->populate($formData);
}
}
}
This works fine and redirects to the auth controller successfully. The code inside the login action of the auth controller is as such:
public function loginAction() {
$formData = $this->_request->getPost();
$authAdapter = new My_Auth_Adapter();
$authAdapter->setTableName('user')
->setIdentity($formData['username'])
->setCredential($formData['password'])
->setIdentityColumn('username')
->setCredentialColumn('password');
$result = $authAdapter->authenticate();
if ($result->isValid()) {
// success, all good
} else {
$this->_forward('index', 'login', 'default', $formData);
}
}
We arrive here fine, and a successful authorisation works as expected. However in my else statement placing another forward back to the original login controller (I wish to populate the username as well as post back an error message) causes the program to hang, although a redirect works fine.
I thought it may be because the login controller is re-detecting the post data and I'm getting caught in an infinite loop, but removing the $formData as the last argument of the forward doesn't change anything.
I've also tried $formData['errMsg'] = 'whatever' above the forward and then checking if the key exists or if it is set in the login controller, but that doesn't change a thing either.
Interestingly, the time out error I receive references the Auth DbTable Adapter:
Fatal error: Maximum execution time of 30 seconds exceeded in /Applications/MAMP/MampServer/mysite/library/Zend/Auth/Adapter/DbTable.php on line 174
Any ideas as to what may be happening?
I think you are infinity looping between loginAction() and indexAction().
Check out the difference between the calls to forward() and redirect() action helpers. The former, forward() internally will change the $request->isDispatched() == false - This means that the front controller will execute the targeted controller action without a new HTTP request.
The outcome of this is that $this->_request->isPost() will always be true and therefore $this->$form->isValid($formData) again will also be true, meaning your going around in circles.
I know the below is a very different to your approach, however I believe it is a more conventional separation of concerns for Zend 1 controllers.
// ... SomeController.php
public function getLoginForm();
public function getSignupForm();
protected function authenticate($username, $password)
{
$authAdapter = new My_Auth_Adapter();
$authAdapter->setTableName('user')
->setIdentity($username)
->setCredential($password)
->setIdentityColumn('username')
->setCredentialColumn('password');
$result = $authAdapter->authenticate();
return ($result->isValid()) ? true : false;
}
public function indexAction()
{
$form = $this->getLoginForm();
$request = $this->getRequest();
if ($request->isPost()) {
if ($form->isValid($request->getPost())) {
if ($this->authenticate($form->getValue('username'), $form->getValue('username'))) {
$this->redirect('/members'); // Successfully logged in
}
}
}
$this->view->form = $form;
}
public function signupAction()
{
// stuff only for signups!
}
Edit To elaborate: forward() is a controller action helper. Its job is simply to modify the Zend_Controller_Request_Http instance. The Zend_Controller_Request_Http class is the one returned when you call $this->getRequest() within a controller.
The Request instance encapsulates all access to $_POST, $_GET and stores then as values within the object. Calls such as $request->setParam('someparam', 123) set or get these values rather than the standard direct access to $_POST['someparam'] or $_GET['someparam'].
The special case is with the values module,controller,action and dispatched. These are the key's used by the Zend_Controller_Front and the Dispatcher when trying to determine the correct controller to instantiate and action method to execute.
A simplified example of how the dispatch loop works:
while(! $request->isDispatched()) {
$request->setDispatched(true);
// If at any point here we change setDispatched(true)
// perhaps in a controller action with a call to forward()
// then the whole dispatch loop will be called again
// perhaps creating a different controller
$controllerName = $request->getControllerName();
$actionName = $request->getActionName();
$controller = new $controllerName();
$controller->$actionName();
}
In the else block:
$this->_redirect($this->url(array('login' => $formData['username'], 'nameOfYourRoute'));
Added a new get variable 'login' to your route and populate your forms login with this variable.
So I'm trying to integrate the PHP facebook SDK/API with codeigniter, because I love codeigniter, but for some reason I keep losing my facebook session as soon as I change pages from my base URL, I have printed the $_session and all i get is Array ( [fb_339393762762289_state] => cb8c201ed66ebcaa60407114aa92f001 ) any ideas why this is happening?
Here is what my controller looks like:
class Main extends CI_Controller {
var $user;
var $log_in_url;
var $log_out_url;
function __construct() {
parent::__construct();
$this->load->library('facebook');
$perams = array(
'scope' => 'user_about_me, read_friendlists',
'redirect_uri' => 'http://www.example.com/'
);
$this->user = $this->facebook->getUser();
$this->log_out_url = $this->facebook->getLogoutUrl();
$this->log_in_url = $this->facebook->getLoginUrl($perams);
print_r($this->user);
print_r($this->log_out_url);
print_r($this->log_in_url);
}
public function index() {
if ($this->user) {
try {
$data['user_profile'] = $this->facebook->api('/me');
} catch (FacebookApiException $e) {
error_log($e);
$this->user = null;
}
}
if ($this->user) {
$data['logout_url'] = $this->log_out_url;
} else {
$data['login_url'] = $this->log_in_url;
}
$data['user'] = $this->user;
$this->load->view('templet/header', $data);
$this->load->view('main view');
$this->load->view('templet/footer');
}
public function account() {
if ($this->user) {
try {
$data['user_profile'] = $this->facebook->api('/me');
} catch (FacebookApiException $e) {
error_log($e);
$this->user = null;
}
}
if ($this->user) {
$data['logout_url'] = $this->log_out_url;
} else {
$data['login_url'] = $this->log_in_url;
}
$data['user'] = $this->user;
$this->load->view('templet/header', $data);
$this->load->view('account');
$this->load->view('templet/footer');
}
from what I can understand from the source code of the api is that it is in charge of handling sessions, so I don't understand why it keeps losing it.
I was thinking it could maybe have something to do with my Htaccess set up.. Ie. my url when i change pages looks like this www.example.com/index.php/controller_name/method_name/
also do i need to do anything with the $_GET vars? because that is one thing i noticed.. there seem to be some things passed in the URL, but they don't continue on to other pages.
any help on this would be greatly appreciated. I am really at a loss.
If you use CodeIgniter Session Library you must know that "The Session class does not utilize native PHP sessions. It generates its own session data"
CodeIgniter Session Class
my problem was somewhat simple, I kept loosing my session data any time I changed pages, and it tuns out the solution was quite simple. in the config file of CI you have to put you websites base URL, and I put and the session was being created for http://www.mysite.com/ so the php sdk/api created one session for the first url and another for the second.. thus i lost all of the data as soon as i changed pages. so it's a simple problem, but took a lot of trouble shooting.
I am not really familiar with Joomla but I have been tasked with writing a module which functionality is irrelevant to the question.
One of the requirements is that if the module is loaded, it should check if the user is logged in and if not - redirect him into a specific URL.
After some searching I came up with something like this, but it's obviously not a working answer:
$user =& JFactory::getUser();
if (!$user->id) {
include_once JPATH_COMPONENT . DIRECTORY_SEPARATOR . "controller.php"; // assuming com_content
$contentController = new ContentController();
$link = JRoute::_("my url");
$contentController->setRedirect($link);
return;
}
I think the problem lies in getting to the controller. Creating a new controller certainly isn't the way to go. Is there a way to get the current controller from a Joomla module and the issue a redirect?
Thank you for any answers.
i call this static function in each of my controllers construct
static function forceLoggedIn(){
$user = JFactory::getUser();
if($user->guest||$user->id == 0)
{
$error = JText::_('YOU MUST BE LOGGED IN');
//base xkè altrimenti andrebbe in loop di redirect
JFactory::getApplication()->redirect(JURI::base(), $error, 'error' );
return false;
}
}
I cant seem to figure out how to create a flexible sidebar containing and login form (Zend_Form) and various module/controller specific links.
The most common solution seems to be using:
echo $this->action('login', 'authentication', 'default');
But apperently this isnt the 'best' way? I've read that this apprently triggers a dispatchloop and thereby take a performance hit?
I've thought about sing a View_Helper for the sidebar:
class Zend_View_Helper_Sidebar extends Zend_View_Helper_Abstract
{
public function sidebar()
{
$sidebar = $this->view->placeholder('sidebar');
$sidebar->setPrefix('<div class="sidebar-element">')
->setSeparator('</div><div class="sidebar-element">')
->setPostfix('</div>');
$sidebar->append(new Form_Login);
$sidebar->append(new Model_Category->getList());
return $sidebar
}
}
In my Form_Login i have action set to /auth/login which contains the following code:
public function loginAction()
{
$request = $this->getRequest();
if($request->isPost()) {
$form = new Form_Login();
$data = $request->getPost();
if($form->isValid($data)) {
$username = $form->getValue('username');
$password = $form->getValue('password');
$users = new Model_DbTable_Users();
$authenticated = $users->login($username, $password);
if($authenticated) {
//Succes - show identity instead of loginForm
} else {
$this->view->loginForm = $form;
$this->render('/index');
}
}
}
}
If I provide the wrong username/password it renders indexAction which is currently empty. This is fine. It also renders my sidebar containing the loginForm as needed, but the form is empty (The user input is not displayed. Neither is no message that the form failed to validate).
The username-field in the form should display the input that the user provided before submitting. And a error message should be displayed.
Any help as to why this is not happing, is very much appriciated.
You are doing your form validation in a loginAction and you said you are currently posting to index action, is that a typo?
Besides that, you are creating two copies of the Form_Login. Once, in the action and once in view helper. If you validate on one instance in the action, you need to display that same instance of the form in the view helper. You could either move all the validation logic into the view helper or you could share the instance between the view helper and the action. I'm going to suggest the latter.
Check in your view helper if a form already exists in the registry. If it does, just use that instance. Otherwise you can create a new instance. Here's a rough example of what I mean:
class Zend_View_Helper_Sidebar extends Zend_View_Helper_Abstract
{
public function sidebar()
{
$sidebar = $this->view->placeholder('sidebar');
$sidebar->setPrefix('<div class="sidebar-element">')
->setSeparator('</div><div class="sidebar-element">')
->setPostfix('</div>');
if(Zend_Registry::isReigistered('loginForm')) {
$loginForm = Zend_Registry::get('loginForm');
} else {
$loginForm = new Form_Login();
}
$sidebar->append($loginForm);
$sidebar->append(new Model_Category->getList());
return $sidebar
}
}
public function loginAction()
{
$form = new Form_Login();
Zend_Registry::set('loginForm', $form);
$request = $this->getRequest();
if($request->isPost()) {
$data = $request->getPost();
if($form->isValid($data)) {
$username = $form->getValue('username');
$password = $form->getValue('password');
$users = new Model_DbTable_Users();
$authenticated = $users->login($username, $password);
if($authenticated) {
//Succes - show identity instead of loginForm
} else {
$this->view->loginForm = $form;
$this->render('/index');
}
}
}
}
Edit:
No, there is no self checking if an instance of a form already exists. You must do this yourself.
I'm pretty sure the suggested way is to use a view helper. As you said in your question, using the action view helper causes another dispatch loop which is bad for performance. I don't know what the verdict is on whether all logic should be kept in the view helper or not.