You are not logged in.
Here's the second part of my Doctrine / Zend_Auth example. In 15 minutes, we create a logout, login and protected area that's reliant on the ZC_Auth_Adapter adapter we created in last week's video. Notice how there's no code in the IndexController exposing the authentication implementation,
Grab a copy of the project or browse the repository.
Also, a big thank you to ServerGrove for extending their support of Zendcasts for January. ServerGrove specializes in Zend Framework hosting and they've offered a 10% rebate on hosting with coupon code "zc". If you're looking for a host, be sure to check them out (referral). They've also added an additional coupon for "Mini Hosting" plans, get $2 off by using code "zcmini".
Offline
Hi Jon,
First of all I would like to say that I'm a big fan of your vid's, makes me view a lot of problems from another perspective.
I must say I watched the code without really checking the video, but it seems like you are doing some bad practices I would like to notify you about.
It's not the responsibility of a user to authenticate it's self. Like a car should not be able to put a traffic light on green. The logic for authentication should be in the authentication class. You can add a non-static function called verifyPassword, and call that function from the authentication.
Type of exceptions should not be checked by exception message. You can subclass the exception class and check it's type by using instanceof.
Things you probably said in the video:
- Passwords should be hashed (with seed);
- It is bad practice to show difference between incorrect user and incorrect password, hackers will be able to use your login interface to check for existing users.
Hope this feedback helps. Keep up the video-tutorials they are great!
Cheers
Hi Reen,
I'm glad you enjoyed the video! I really appreciate your feedback about this project. Let me respond to your comments:
Hi Jon,
It's not the responsibility of a user to authenticate it's self. Like a car should not be able to put a traffic light on green. The logic for authentication should be in the authentication class. You can add a non-static function called verifyPassword, and call that function from the authentication.
The user is not authenticating himself, the use Model, however is. I'm also using the Model_User class as a method of storing any business rules related to authentication. If the code were in the authentication class, it would couple the database querying engine (in this case Doctrine) to the authentication code. Alternatively, a data-table gateway could've been implemented so that the Model_User class could be used exclusively as a value-object. This, of course, would add to the complexity of the implementation in an area that the video wasn't focused.
Type of exceptions should not be checked by exception message. You can subclass the exception class and check it's type by using instanceof.
There's been a lot of debate about this within the Zend community, however you're absolutely right that a OOP purist would do type checking rather than error code checking. However, the disadvantage to such heavy Exception class implementations is that you start creating Exceptions for every single outcome, my own experience of seeing hundreds of lines of catch blocks in Java has led me to prefer a error-code-based comparison, using the Exception model for more generic exception handling. Furthermore, having multiple exceptions and then explaining their use would blur the overall focus of the video, which is the Zend_Controller implementation.
Things you probably said in the video:
- Passwords should be hashed (with seed);
- It is bad practice to show difference between incorrect user and incorrect password, hackers will be able to use your login interface to check for existing users.Hope this feedback helps. Keep up the video-tutorials they are great!
Cheers
Thanks for mentioning the passwords here. Of course passwords should be hashed! Preferably with a salt as well. This is mentioned in the video.
In terms of it being a bad practice to say a user is not found, I've never found or read anything of the sort. I've also seen this functionality widely used in web applications. I would also conjecture that a hacker could use a registration interface to discern the same data.
Offline
Hi again,
First of all, I do understand that you have to make choices in your video and that you can't cover all.
The user is not authenticating himself, the use Model, however is.
From my point of view it is like you're saying "It's ok to let the car controll the traffic light as long as you make the functions static." I think the Auth_Adapter is an adapter because it only works for certain situations. Like the MySQL DB adapter only works for MySQL. There is no point in making it so abstract that it works in every case, because it will only move your problem to another place.
Furthermore, having multiple exceptions and then explaining their use would blur the overall focus of the video, which is the Zend_Controller implementation.
Agreed.
I would also conjecture that a hacker could use a registration interface to discern the same data.
Registration forms should be protected with a captcha functionality, making it hard to automate this process. Some applications might also have a non-public register interface.
Hi Reen,
I definitely see your point about the Model. Personally, I would rather keep my Doctrine queries outside of any non-Model_* classes, however you do a good point for keeping them in the adapter.
Good point about Captcha functionality! I guess it really depends on the kind of application.
Offline
What exactly does the build all reload do?
Does it not overwrite your authenticate method?
Offline
nope, only the base classes
Offline
Great podcast Jon - fantastic for a new Zend user like myself.
However, after completing the stages in this episode I seem to be getting an autoloader issue trying to find the Model classes. Maybe you can help me resolve it.
My doctrine application.ini section looks like:
doctrine.generate_models_options.pearStyle = true
doctrine.generate_models_options.generateTableClasses = false
doctrine.generate_models_options.generateBaseClasses = true
doctrine.generate_models_options.baseClassPrefix = "Base_"
doctrine.generate_models_options.classPrefixFiles = false
doctrine.generate_models_options.classPrefix = "Model_"
doctrine.generate_models_options.baseClassesDirectory =
Which generates the Models folder structure:
application/models/Base/User.php
application/models/User.php
Both classes have the prefix: Model_User & Model_Base_User
When I come to login to the page (do the postback) I get the following exception:
Fatal error: Class 'Model_User' not found in /usr/local/zend/apache2/htdocs/Project/library/FME/Auth/Adapter.php on line 23
The Adapter.php class being the one you wrote in the episode that is dependent on Model_User.
The classloader cannot find the class/file. I have modified the doctrine config trying many permutations trying to fix this but it does not resolve the Zend issue, and just results in Doctrine CLI throwinf the following:
build-all-reload - Are you sure you wish to drop your databases? (y/n)
y
build-all-reload - Successfully dropped database for connection named 'doctrine'
build-all-reload - Generated models successfully from YAML schema
build-all-reload - Successfully created database for connection named 'doctrine'
build-all-reload - Created tables successfully
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'fme.user' doesn't exist. Failing Query: "DELETE FROM user"
If I set:
doctrine.generate_models_options.pearStyle = false (instead of true)
then the Doctrine CLI works fine and puts the user data into the table correctly - however Zend still complains about the class missing.
Thanks for any pointers you can give me to fix this,
Offline
Hi Jon, I want ask about OOP, I'm still not strong in OOP ![]()
Are function in Model Doctrine must static function?
If we already use doctrine model, are we necessary use a service layer to insert 2 table/model?
Offline
Hello digitalbanana,
have you find an issue to your problem?? I have exactly the same...
Thanks
Very good job Jon for all your podcasts! its a pleasure to learn with your tutorials! ![]()
Offline
I find it bad style to store the whole user-object inside the session.
Is there a way to just store the id of the user, and fetch a fresh version of the object on page-load?
It will generate an additional DB-trip, but it will guarantee that all changes made externally (e.g. via database) will be loaded aswell.
iirc you mentioned a followup for this problem at the end, but I couldn't find it. Can someone point me to the cast if it already exists?
Offline
Fixed that.
I'm now just storing the user-id as the identity (because that won't change).
On site-request (preDispatch from the controllers), I'm calling and Model_User::currentUser, wich returns false on not-logged in, and the current user on logged in.
Model_User::currentUser basicly grabs the identity and returns the User corrensponding to the User-ID
Offline
In the end of the video you talk about a follow-up video, but it seems to never have come?
Offline
Harri,
you'll have to forgive me, what did I promise to follow up in a future video?
Offline
Well you didn't say follow up but you described what you would look at in the next episode. It was about the shortcomings of the method used in this video. The next video is the introduction to Zend_Mail (which i very much liked and have come to very good use for me).
I'm not trying to be difficult here but was only curious because I was interested in what you said you where going to cover.
You find it in the end of the video at 15:15.
Offline