Computer programming in PHP for business and passion
In: PHP| Security| Zend Framework
3 Jul 2009After a long pause i’m come back on my blog with a post about the development of a secure web login system in PHP with the use of Zend Framework. The issue to build a login system in a web application is quite common. The security aspect of a login system is absolutely important and in this post i have summarized some of the main security points. Of course this is not the final solution but, in my opinion, is a good point of start for PHP developers.
I have built a simple Zend Framework application with a login and home page. The login is a form with a username and a password text box. This fields are mapped into a MySQL database, with a simple table with the following structure:
1 2 3 4 5 6 7 8 9 | CREATE TABLE users ( username VARCHAR(32) NOT NULL , password CHAR(32) NOT NULL , salt CHAR(20) NOT NULL , email VARCHAR(80) , active BOOLEAN NOT NULL DEFAULT 1 , last_access DATETIME NOT NULL , PRIMARY KEY (username) ); |
As you can see we store the password with a CHAR(32) field, this is because we use the MD5() hash function to secure the storing of the data. As you know if you store a password with an hash function is, in theory, impossible to invert the hash value and find the password in plain. I wrote in theory because, as Joe Devon writes in his comment, you can use Google to retrieves the most common hash values (for instance try this web site http://md5.rednoize.com/).
In order to improve the security of the MD5 i used a salt value. I added a salt field of CHAR(20) into the users table with a random string value. The MD5 of the password is generated with a MD5(CONCAT(salt,’password’)) where ‘password’ is the password string value. With this salt method is more difficult to use a dictionary attack of the MD5 values.
With this system even the administrator of the site can’t know the password of their users. This is very important for privacy reason (do you trust websites that are able to recover your password?).
This application uses the following Zend Framework classes to build the secure login:
I have structured the application into the following directories:

The main directoris are: application, etc, library, public.
In application i put the usual MVC structure of a Zend Framework, with the files bootstrap.php and Initializer.php. The Initializer class is a plug-in of the Front Controller where i wrote the authentication check of the login. I think it’s a good solution for a login system because in this way we can manage the authentication system without any modification of the Controllers. This means that if a user is able to see a Controllers he is just authenticated.
In the etc directory i put the configuration file config.ini and the database structure into the sub-dir db.
In the library directory i put the common php classes that i reuse in my Zend Framework applications and a sub-directory name Forms with all the forms of the application.
In the public directory i put the document root of the application with .css, .js, images and the index.php that is the only php scripts published into the document root.
We focus now on the Initializer plugin, that is the core of the login system.
This Initializer plugin comes from the structure proposed by the Zend Studio for Eclipse where i have inserted some more methods.
In particular i have added the preDispatch and checkSession methods.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /** * preDispatch */ public function preDispatch () { $this->_controller= $this->_front->getRequest()->getControllerName(); if (($this->_controller!='index') && ($this->_controller!='error')) { if (Globals::getConfig()->authentication->active) { $this->checkSession(); } } } /** * checkSession */ private function checkSession() { if (empty(Globals::getSession()->username)) { $this->_response->setRedirect('/index/login')->sendResponse(); exit; } } |
The preDispatch method is called from the Zend Framework flow first to dispatch every actions and for this reason it’s a good point where insert an authentication system. In the preDispatch method we get the name of the Controller and we check if the actual controller is different from index and error, if it’s true i call the checkSession method.
Notice that i used another if to check if the authentication system is on, using the attribute active of the config.ini file. This system can be useful to switch on and off the authentication, changing a single value into a configuration file.
The index and error are the controllers out of the authentication system, this because they contain public pages that must be visible without autentication.
The checkSession method is very simple, it checks if the session variable username is empty, if it is empty means that the user is not authenticated and the execution flow must be redirect to the login page. Note the presence of the exit() function, it’s very important because without it an authorized user can execute actions because the flow of Zend Framework continues after the sendResponse (thanks to Ankit for his comment).
As you have noticed i used the Globals class to take some singleton objects related to the management of the database conncetion, the session and the configuration file. I usually built these singletons because i have only one instance of database, session and configuration file during the execution of my PHP applications. Moreover with a singleton i can speed up the reading of these values during the execution of the same instance of an application.
The login form of the application is built into the library/Forms/Login.php script. I used the Zend_Form_Element_Hash class of the Zend Framework to secure against CSRF attacks (click here for info about CSRF attacks). I used the setSalt method to improve the security with a pseudo-random value obtained with the function md5(uniqid(rand(), TRUE)) and the setTimeout to set a Time To Live (TTL) for the token (the value of timeout is specified into the config.ini).
... $token = new Zend_Form_Element_Hash('token'); $token->setSalt(md5(uniqid(rand(), TRUE))); $token->setTimeout(Globals::getConfig()->authentication->timeout); $this->addElement($token); ...
With this hidden value, the token, inserted into a form we are sure that the POST data comes from our page and not from others.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | ... public function loginAction() { $flash = $this->_helper->getHelper('flashMessenger'); if ($flash->hasMessages()) { $this->view->message = $flash->getMessages(); } $this->view->form= new Forms_Login(); $this->render('login'); } ... public function submitAction() { $form= new Forms_Login(); if (!$form->isValid($_POST)) { if (count($form->getErrors('token')) > 0) { return $this->_forward('csrf-forbidden', 'error'); } else { $this->view->form = $form; return $this->render('login'); } } $username= $this->getRequest()->getPost('username'); $password= $this->getRequest()->getPost('password'); $authAdapter = new Zend_Auth_Adapter_DbTable( Globals::getDbConnection(), 'users', 'username', 'password', 'MD5(CONCAT(salt,?)) AND active=1' ); $authAdapter->setIdentity($username) ->setCredential($password); $result= $authAdapter->authenticate(); Zend_Session::regenerateId(); if (!$result->isValid()) { $this->_helper->flashMessenger->addMessage("Authentication error."); $this->_redirect('/index/login'); } else { Globals::getSession()->username= $result->getIdentity(); Zend_Loader::loadClass('Users'); $users= new Users(); $data= array ('last_access' => date('Y-m-d H:i:s')); $where= $users->getAdapter()->quoteInto('username = ?', Globals::getSession()->username); if (!$users->update($data,$where)) { throw new Zend_Exception('Error on update last_access'); } $this->_redirect('/home'); } } ... |
In the loginAction i built the login form (line 7).
The data of the login page are submitted to the submitAction method. In this action we check the validation of the form (line 13). If there’s a problem on the token data this means that we are under a CSRF attack so we can redirect to a specific error page named csrf-forbidden. The csrf-forbidden page gives a 403 Forbidden value, this to prevent that we send the form data to an unauthorized user (for more info about this subject read the post “Preventing CSRF properly” of Tom Graham).
For the authentication of the user we used the Zend_Auth_Adapter_DbTable adapter (line 23). We check the authorization using the MD5 of the password (MD5(?), where ? is $password) only for the active users (active=1).
If the user is authenticated we update the last_access field of the user table and we redirect to the home page (lines 38-46).
If the user is not authenticated we redirect to the login page with the error message ‘Authentication error.’.
Notice that we regenerated the session id with the Zend_Session::regenerateId() during the login (line 33) and we clean the session during the logout (line 25 of the logoutAction into the HomeController). This for security reason in order to mitigate the possibility of a session fixation attack (click here for info about session fixation).
In this post i didn’t talk about SQL Injection, why? Because the Zend_Db class that we used in this application uses placeholder quoting to prevent SQL Injection. Moreover we used the validator of the Zend_Form in order to filter the input values of username and password (see the addValidators method in the Forms_Login class). So the mantra “Filter Input, Escape Output” is respected.
In this post i provided a secure login application with the use of Zend Framework. The securiy aspect of this application are:
One of the unsecure point of this application is that the username and the password are submitted in plain text. Any attacker that is able to sniff the HTTP communication between client and server can capture these information.
In order to build a real secure system i suggest to use the Secure Sockets Layer protocol (SSL), this is the only way to encrypt the communication between client and server.
Here you can find the source code of the Secure Login Application. In order to execute the code you have to create a MySQL database using the SQL structure reported in /etc/db/dbUsers.sql and modify the etc/config.ini with your db permission.
I tested the application with the Zend Framework v. 1.8.4.
Click here to download the source code (ZFSecureLogin.zip, 13Kb)
This is my personal blog about computer programming in PHP for business and passion. I'm Enrico Zimuel a Software Engineer since 1996. I work as Senior Consultant & Architect at Zend Technologies. For more info about me visit my web site.
47 Responses to Build a secure login with Zend Framework
Zend Framework in Action » Secure login with Zend Framework
July 4th, 2009 at 8:23 am
[...] Zimuel has posted an article on how to build a secure login with Zend Framework: After a long pause i’m come back on my blog with a post about the development of a secure web [...]
Joe Devon
July 11th, 2009 at 9:54 am
Thanks for sharing your interesting approach and glad to have you back writing.
I wanted to add a couple points. The MD5 password field length is fixed, so char is probably more appropriate than varchar.
Re: strength of MD5:
http://it.slashdot.org/article.pl?sid=07/11/20/1914209
If you salt the MD5, then you’ve got a more secure setup. Add a column for each user and a random unique salt for each and it’s even better.
Enrico Zimuel
July 11th, 2009 at 6:02 pm
Thank you Joe, i just updated the post with your suggestions. You are absolutely right, a random salt definitely improves the security of the MD5.
Michael Krapf
July 15th, 2009 at 7:38 pm
Your tutorial is top notch and I appreciate the effort.
Please bear with me as I am a php novice in training.
Is it necessary to install the entire Zend backage in the library folder?
How do I add new users? I am familiar with phpMyAdmin, but if the passwords are protected from the admin, shouldn’t the user have the ability to submit their own credentials?
Any additional information for a newbie would be very helpful and appreciated.
Enrico Zimuel
July 16th, 2009 at 10:30 am
If you want to use only some classes of the Zend Framework (ZF), without the MVC feature, you can install only these classes into the /library directory of the ZF.
Anyway my suggestion is to install all the files of the /library folder of the ZF. In this way you can use the same ZF installation for all the php applications of your server.
Related to the question on how add new users into the MySQL table ‘users’, you can use this simple query:
SET @salt=SUBSTRING(MD5(RAND()),-20);
INSERT INTO users (username,password,salt,email) VALUES (’user’,MD5(CONCAT(@salt,’password’)), @salt, ‘email’);
where ‘user’ is the username, ‘password’ is the password in plain and ‘email’ is the email address of the user.
As you can imagine there are a lot of others way to create a random salt, this one is very easy and it uses directly the MySQL engine to generate the salt.
You can create a simple php page to add a user account directly from the user subscription page (better if with SSL protection). In this way the admin of the web pages doesn’t know the password of the users.
Stephen Karl Lang
July 16th, 2009 at 7:45 pm
Great post, Enrico. I especially appreciate how these methods can also be applied to other frameworks and/or technologies. You have a new subscriber
Kalpesh
July 20th, 2009 at 10:28 am
Hi,
I like your tutorial.
I use this in my project.
I am using Model_Db_Table to access database.
To insert user name and password there is a function DbTable
called $this->insert($data);
How can i create password with md5 salt.
If you help me with this then i will be much thankful to you.
Again thanks for this tutorial.
Enrico Zimuel
July 20th, 2009 at 11:08 am
For instance you can use this code:
Zend_Loader::loadClass(’Users’);
$user= new Users();
$salt=substr(md5(mt_rand()),0,20);
$md5Password=md5($salt.$password);
$data= array (
‘username’ => $username,
’salt’ => $salt,
‘password’ => $md5Password,
‘email’ => $email
);
if (!$user->insert($data)) {
// @todo error
}
Kalpesh
July 27th, 2009 at 1:48 pm
Hi, thanks for your reply,
IT works
But how can i store user name in session.
I try to use Zend_Session_Namespace in submit Action before it redirects to home page
$sess = new Zend_Session_Namespace(’MyNamespace’);
$sess->username =’Kalpesh’ ;
but when i go home page i try to print session value called username.
It doesn’t print it.
Is there anothe way to store username in session.
And again thanks for reply
Hari K T
July 27th, 2009 at 7:48 pm
Good one . Really a nice effort to help the newbie like me .
Wish u good luck .
Bye till we see for nxt post .
Joe Devon
July 28th, 2009 at 5:47 pm
Something else to consider….a pagewide or sitewide salt as well (depending on the situation). The reason being, if someone breaks into your database and has the random salts that were generated and stored in the dB, he can brute force the entire database at his leisure and pull out passwords…whereas adding a pagewide-salt into the code, he’d have to break into both the database and the source code. Just an extra layer of protection.
P.S. I use Zend_Config_Ini to pull in the full form into Zend_Form, including the csrf, in a class I wrote to automate it….. Something like so:
$config = new Zend_Config_Ini(APPLICATION_PATH
. ‘/configs/’. $form . ‘.ini’
,APPLICATION_ENV);
$formConfig[$form] = new Zend_Form($config->$form);
Obviously I can’t use a function to set a random salt in the config. Is there any way of doing this as well as the ttl in the config without invoking any methods on the token as in your code above?
Also, you’re time to live is set to 60. Is that minutes?! The ttl in my forms seem pretty short. Maybe I should increase it too. I wonder what the default is.
David
August 3rd, 2009 at 8:39 am
Excellent tutorial, especially for a ZF noob like me. Very helpful, thanks.
Justin Hendrickson
August 26th, 2009 at 2:59 pm
One quick pet peeve correction:
uniqid() creates a unique identifier. Hashing that value with md5() makes it “less unique”. http://us.php.net/manual/en/function.uniqid.php#91126
Enrico Zimuel
August 26th, 2009 at 6:48 pm
Thanks for your suggestion. I read only the first part of the php manual where is written that md5(uniqid(mt_rand(), true)); is better because difficult to guess. Using the md5 function there is a probability (very low) to generate the same output from different inputs.
Anurag Jain
August 28th, 2009 at 11:36 am
Hello ,
Let me go straight.
Will this work on 1.9, if no then what are the possible changes?
Anurag
Enrico Zimuel
August 31st, 2009 at 5:29 pm
I just tried with the last version 1.9.2 of the Zend Framework and it works fine.
Fozzy
September 29th, 2009 at 3:34 pm
Hey,
I just stumbled up on your tutorial. Thanks for taking the time to write it.
One quick question, is it safe to separate the salt from the password? Most security stuff I have seen mentions prepend/append the salt to the password or some cleaver similar thing.
However, I don’t see how one could make an easy SQL statement that would work in this fashion, so I would guess a custom auth_adaptor would be needed.
Curious as to there being any real reason do combine the salt with the password? Of if it’s doesn’t really provide any more security as someone who could hack your DB prob. hacked your source code and could figure out the salt, either way?
Chris UK
September 30th, 2009 at 11:02 am
Finally a Auth example app that works for Zend Framework 1.9!! Thank you so much.
01kuzma
September 30th, 2009 at 12:51 pm
Hi!
It’s great tutorial and thank you for it!
I’m novice in ZF so maybe it will sound a bit stupid
The checkSession() function checks if the user is authorized to see the secured content. So this function must be called each time from each controller?
Or it should be called only from Auth controller in index action like this:
public function indexAction()
{
$this-> checkSession();
$this->view->auth=Globals::getConfig()->authentication->active;
}
Than you!
Enrico Zimuel
October 3rd, 2009 at 8:41 am
You don’t have to call the checkSession() in every controller. This function is called into the Plug-in Controller Initializer for every http request.
In this way if someone is able to see a controller that means that he is authorized.
Enrico Zimuel
October 3rd, 2009 at 8:50 am
In my example i use a salt random value to increase the entropy of the password. This method is used to prevent dictionary attacks of the hashed passwords. If you see in the code i prepended the salt with the password and after i generate the MD5. This is built with the MySQL query: MD5(CONCAT(salt,’password’)) where ‘password’ is the password string value.
If you want to improve more the security of the login system you can store the salt values in a different way and not in the same table.
Refactoring the ZF Secure Login example with Zend_Application - Zimuel’s blog
October 22nd, 2009 at 6:26 am
[...] this post i’m going to refactoring the ZF Secure Login application, that i provided in my previous post, using the new Zend_Application class, out from the version 1.8 of Zend [...]
Ankit
November 5th, 2009 at 6:22 pm
I think there is a problem with your statement:
$this->_response->setRedirect(’/index/login’)->sendResponse();
in checkSession() function. Above method does redirect the user, but it also performs and underlying request. I believe you need to also have exit; afterwards.
Heshan Peiris
November 6th, 2009 at 7:10 am
I’m new to zend framework and this article is really worth for me to get familiar with framework. Thank you for the article.
Enrico Zimuel
November 6th, 2009 at 2:20 pm
Hi Ankit,
generally speaking your comment is right, but in this case there are not other instructions after the sendResponse() so it works fine without the exit statement.
Ankit
November 6th, 2009 at 7:24 pm
Hi Enrico,
Thanks for your reply. Are you saying that Zend will not go ahead with processing the request after preDispatch() function returns?
I am asking because I have seen that if I do not have “exit;” ZF actually processes the request and then forwards the user to the redirect location.
This is a problem because, an authorized user can actually perform an action without actually logging in.
I don’t know if this is due to not having exit; or having one of my settings set incorrectly.
Enrico Zimuel
November 9th, 2009 at 1:59 pm
Hi Ankit,
if you use the sendResponse() you force the flow of the dispatcher sending the output to the browser.
In this way an unauthorized user cannot execute actions without login.
For more info: http://framework.zend.com/manual/en/zend.controller.response.html
Ankit
November 10th, 2009 at 11:54 pm
Hi Enrico,
It is correct that the user will be eventually forwarded to the login page. However, I believe that ZF still processes the underlying request. Suppose instead of going to index, an unknown user (not logged in) was going to let’s say…
/customer/deleteCustomer/?customer_id=12.
Here, unless we exit(), ZF would execute the deletion and then forward the user to the login page.
Enrico Zimuel
November 11th, 2009 at 9:47 am
Hi Ankit,
you are absolutely right! Without the exit() an authorized user can execute actions.
When i built it I was focused only on the view side, that is not rendered without authorization.
It was my fault, sorry.
I modified the source code of the example.
Thank you very much Ankit for your suggestion.
Rodrigo Ferrari
November 11th, 2009 at 2:28 pm
Hello,
Thanks for this greate share, but I´m not able to make it run. Just Copied all the files and add ZF 1.8 and tryed to run, the response is that 404 no found the page http://localhost/index/login And the response is The requested URL /index/login was not found on this server.
How can I fix it?! I´m new to ZF.
Thanks.
Snowcore
November 11th, 2009 at 5:01 pm
Thanks for the great tutorial!
Enrico Zimuel
November 11th, 2009 at 5:11 pm
Hi Rodrigo,
I think you have a problem of configuration of your apache.
Check these points:
- the .htaccess file in the public folder
- the configuration of apache about the mod_rewrite
For more info: http://framework.zend.com/wiki/display/ZFDEV/Configuring+Your+URL+Rewriter
sasikumar
November 17th, 2009 at 4:11 pm
when run your secure login script the I got the follwing error
Not Found
The requested URL /index/login was not found on this server.
the htacces file available in public folder
here this our htacces
RewriteEngine on
RewriteRule !\.(js|ico|gif|jpg|png|css)$ index.php
please tell me what is the solutions
Enrico Zimuel
November 18th, 2009 at 8:49 am
You have to check the configuration of your web server.
If you use Apache you have to switch on the mod_rewrite and check the directive AllowOverride.
Moreover if you use a virtual host you have to insert the directive AccessFileName .htaccess.
For more info visit this link: http://framework.zend.com/wiki/display/ZFDEV/Configuring+Your+URL+Rewriter
Charles
January 21st, 2010 at 3:39 pm
A really well written and useful tutorial which has helped me loads.
Gins
February 17th, 2010 at 3:36 pm
HI…
A good article……
I do have a doubt..i am using zend-auth for authentication.It works fine.what i want to do is increase timeout.Since the default session is used i can’t or i dont know how to increase the timeout..Any help would be great!!
I tried to initalize a object of Zend_auth and set expiration seconds to custom didn’t wrk. Also set gcmaxlife time…no way??please help me…
Enrico Zimuel
March 1st, 2010 at 9:09 am
Hi Gins,
in order to modify the timeout of the session you can use the method setExprirationSeconds() of Zend_Session.
You can specify to use a different Zend_Session namespace for the Zend_Auth adapter using this code:
$auth->setStorage(new Zend_Auth_Storage_Session(’someNamespace’));
where $auth is an instance of Zend_Auth and ’someNamespace’ is the name of your session.
After this you can use the setExpirationSeconds to modify the timeout on the session.
pzajdel
March 1st, 2010 at 9:12 am
Hi.
First of all, excellent article. Many thanks for sharing.
But of course there always has to be some ‘but’.
Any idea why when I type a wrong url in browser:
http://localhost/zfsecurelogin/public/whatever
http://localhost/zfsecurelogin/public/index/whatever
What I get is:
“Fatal error: Uncaught exception ‘Zend_Controller_Dispatcher_Exception’ with message ‘Invalid controller specified (whatever)’ (…) Zend\Controller\Dispatcher\Standard.php on line 242″
or
“Fatal error: Uncaught exception ‘Zend_Controller_Action_Exception’ with message ‘Action “whatever” (…) thrown in E:\php\Zend\library\Zend\Controller\Action.php on line 485″
Instead of:
“HTTP/1.1 404 Not Found”
ErrorController line 29.
I’m using new ZF 1.10 and for some reason (guess different Apache configuration or no vhost?) I needed to change Initializer.php line 216 to:
$this->_response->setRedirect(’index/login’)->sendResponse();
I would use some help here. So I hope thanks in advace! xD
Btw. what do you think about using another table in DB just for salt and username (more often id) foreign key?
Enrico Zimuel
March 1st, 2010 at 9:18 am
Did you tried to use the new example of Secure Login of my post “Refactoring the ZF Secure Login example with Zend_Application”?
I tried the example with the ZF 1.10.2 and it works fine, with 404 Not Found managed by ErrorController.
To manage the redirect issue you have to use a virtual host to point the root of the application or you can define a PHP constant and add it to the redicrect calls to manage the relative web path.
Moreover you can use the RewriteBase directive in the .htaccess to redicrect the url in your folder path.
pzajdel
March 1st, 2010 at 9:34 am
New example: not yet, but I will.
As to the ‘not working’ ErrorController, I just figured it out. I didn’t pay attention to the lines 74-82 in Initializer. Comment does the thing of course. Silly me.
Thanks again!
PHPGangsta
March 18th, 2010 at 12:10 pm
Nice article and some very important information in it.
But I missed an important protection against brute-force-attacks. With your code it is still possible to write a little script which gets the html page (to get the token) and then try to login. Because there is no protection it is possible to do this from many computers (bot net?) and as fast as the internet connection is, so the attacker could try hundreds of usernames/passwords per second.
Would be nice if you could add some information there.
Enrico Zimuel
March 18th, 2010 at 1:00 pm
In order to improve the security of this Secure Login against brute-force-attacks you have to store the IP address of the request and block it for a while after n failed login.
This is the most common approach to limit the brute-force-attacks. You can use the $_SERVER['REMOTE_ADDR'] variable of PHP to get the IP address and store it in a temporary file/db with a timestamp. For instance, you can block the access after 5 failed login for 5 minutes and increase this time if the same IP fails again.
DNoe
May 10th, 2010 at 2:41 pm
Greetings -
I am curious as to why you do not use numerical user IDs. Almost all implementations of user login systems I have worked on use a unique user ID as a primary key. I realize that the username field will be unique, so perhaps this is more of a habit than a necessity. Is this eliminated here for simplicity or is there more to it than that?
Thanks for the tutorial!
DNoe
Enrico Zimuel
May 11th, 2010 at 11:11 pm
I used the username as primary key because it’s a unique key for the table. In general if I have a table with a field that is unique I use this field as primary key. In this way you can implement the data integration in a easy way. Think about the duplication of id, in this way the DBMS will check it and not the PHP application.
Luca
May 20th, 2010 at 7:48 pm
Hi! Thanks for the post… App works fine for me but I have a problem. I run the app in a subdirectory with no virtual host. I ask you for a little help, maybe you can resolve my trouble quickly….
thats my htaccess in public folder…
RewriteEngine on
RewriteBase /workspace/zfsecurelogin/public/
RewriteRule !\.(js|ico|gif|jpg|png|css)$ index.php
my app run if I specify controller/action like this:
http://localhost/workspace/zfsecurelogin/public/index/login
if I open http://localhost/workspace/zfsecurelogin/public/
_redirect takes me to localhost with 404 error.
>>>> BAD >>>>> http://localhost/index/login
I added the setBaseUrl in Front controller, mod rewrite works and I tried to use also Zend Redirector Helper with no success… I tried to solve this but I can’t see the end….
why this???
Thanks
Enrico Zimuel
May 20th, 2010 at 9:52 pm
You have to use a virtual host to run the example in the correct way. For security reason you have to expose only the public folder to the web server. In your example you published also the application folder and this is dangerous.
Luca
May 21st, 2010 at 12:38 am
Ok Enrico, thank you for advice.