views:

3994

answers:

5
+7  Q: 

Zend Auth and ACL

Hi there,

I am hoping some can help me a little bit, I am currently developing my first site using a PHP framework, part of the site is spilt into a members area, this is where my confusion begins to surface, withing the members area I want normal members to be able to add new comments and edit there own comments, simple enough that I can just check the posters name against the username that is stored in the session, my confusion comes with differentiating between the 'normal' users and the higher level users who have the ability to delete and modify any ones comments etc, they should also be able to access the admin section of the site.

My question is should all user login through the same Zend_Auth controller, or should there be seperate controllers using Zend_Auth for each type of user or can all that be dealt with using Zend_Acl? Any help, advice, article, or tutorials would be greatfully appreciated. Personally I think the Zend documentation is a little raw on some classes.

Thanks in advance

sico87

+4  A: 

Yes, in most cases all of your authentication should go through the same controller. However, Zend Auth is not a controller type. Zend Auth is an API for utilizing common authentication methods like a database or http. Its job is really just to be a wrapper around the grunt work of writing authentication code.

Zend Acl is what you are looking for to distinguish between normal and privileged users. You only involve Zend Acl after the users have authenticated and logged in.

Most of what you need is in the ZF documentation. I read almost all of the documentation for Auth and Acl before it made great sense to me. Even though ZF's Auth, ACL, Storage_* and other classes are used very closely together, they all serve very distinct purposes. With a little time you will see that they build on each other nicely.

A couple of links to get you started:

Pádraic Brady's ZF Tutorial

Zend's DevZone article on ACL and MVC

Barrett Conrad
A: 

Ok, thanks for reply that has cleared it up a little bit for me thanks, so how to I compare the roles I set for the ACL and the role that user holds, at the moment all the user data is help in db table, so for exampl there could be a user called joe_bloggs and he would be have a user of defaultRole, in my index I currently have it loaded in like this

require_once 'Zend/Acl/Resource.php';
$acl->add(new Zend_Acl_Resource('news'))
->allow('defaultRole', 'news')
->deny('defaultRole', 'news', 'add');

So how do I then get it to match up the data that the table holds? Can you see where I am getting confused now? Do I hold that the user level in a session variable and match it agains that? Please help I think my brain and patience are about to explode :-(

Thanks again

sico87

sico87
integrate this into your question or better open a new question!
tharkun
Store the name of user's role in the session ($_SESSION['role']), or the zend_auth identity.Then you just:$resource = new Zend_Acl_Resource('news');$acl->->allow('defaultRole', $resource); if($acl->isAllowed($_SESSION['role'], $resource, $privilege)) { //do stuff
lo_fye
+8  A: 

I recommend the book "Zend Framework in Action" from Manning Publications as a great, up-to-date, introduction to this. It's available as PDF download, so you can have it now :)

But to answer this particular question:

Let's start by defining two key terms. The "Auth" in Zend_Auth refers to Authentication, which proves someone is who they say they are (i.e. login). The "A" in Zend_Acl refers to Authorization, which proves someone has the right to do what they're trying to do (i.e. access control).

Assuming the user has a single role... Store the user's roles in the "identity" you get as part of Zend_Auth. At login:

$auth = Zend_Auth::getInstance();
$identity = new stdClass();
$identity->user_pk = $user->getPrimaryKey();
$identity->user_name = $user->getName();
$identity->role = $user->getRole(); // select * from user_role where user_pk=xxx
$auth->getStorage()->write($identity);

In Controller:

$acl->add(new Zend_Acl_Resource('news'))
->allow('defaultRole', 'news');

Everything is denied by default, so you don't really need to specify:

->deny('defaultRole', 'news', 'add');

Further on in the Controller's code:

$identity = Zend_Auth::getInstance()->getIdentity();
if(!$acl->isAllowed($identity->role, 'news', 'add'))
{
   header('Location: http://www.yoursite.com/error/unauthorized');
}

If the user's identity is not allowed to do "news->add", it will redirect them to the unauthorized page (assuming you've made such a page).

If the user had >1 role, you'd store an array of roles in their identity. Then your check would go something like this:

$identity = Zend_Auth::getInstance()->getIdentity();
$isAllowed = false;
foreach($identity->role as $role)
{
   if($acl->isAllowed($role, 'news', 'add'))
   {
      $isAllowed = true;
   }
}
if(!$isAllowed)
{  // if NO ROLES have access, redirect to unauthorized page
   header('Location: http://www.yoursite.com/error/unauthorized');
}

Hope that helps.

lo_fye
+2  A: 

Hi sico87

I can understand why you are getting confused. I was/am still a bit confused. So, unfortunately I cannot answer your question directly. But, one thing i am doing in order to clarify all this stuff in my head is to think in terms of 'domain objects' as opposed to database records.

My tactic to deal with this issue is to create my own Auth Adaptor that is passed a 'User Base Object' along with the user credentials. My 'User Base' is kind of like a repository of users.

So the Zend Auth is left being 'an interface' to other Zend Components whilst i still have a bit more control over my system for storing and accessing 'Users'. My User_Base class could be a wrapper around a Zend Db tbl or even just have some hard code in it that i can use for testing.

So in general-

  • design your own model of a 'user'

  • design your own Auth Adaptor - starting with the minimum interface required as outlined here: http://framework.zend.com/manual/en/zend.auth.html

  • and just keep it all simple and go slowly as you learn more about it.

well that's what i am gonna do anyway.

I aint even gonna bother with Zend ACL just yet til i have Auth clear in my head.


I'm revamping a legacy site and converting it to Zend MVC

These are some things (perhaps unconventional) that I have had to get to grips with for my 'model' to work. :

  • an app may be used by users from multiple 'user bases' - openID, legacy users table, new users table, fleeting guests, etc
  • a guest's identity might just be a hash created when they first arrive
  • whereas, a legacy user's identity might be represented by an id in the legacy users table
  • users and user_accounts are separate things. don't try to mix them into one concept cos it could get complicated.
  • there may be many different types of accounts in the system. I.e. Buyers Accounts versus Sellers accounts. Readers_Account versus Writers_Account
  • accounts 'have' users - 'primary account holder', 'admin super user', etc
  • the relationship between the users and an account are represented by, say, 'account_users' (a local subset of all users in all user bases)
  • roles arew attached to account_users (the users of that particular account).(As opposed to roles floating around )
  • don't be afraid to have more than one Zend application on a server to represent a website - e.g admin app, members app, front end app.
  • don't be afraid to let these apps use model objects stored in say 'shared models' folder, with the only model code that directly relates to the individual app sitting in the /application/models/foomodel folders.
  • each app might have its own custom Auth adaptor
  • an admin auth adaptor may only allow users from the 'admin users table' whereas a front end app's Auth adaptor might be able to authenticate users from the guest userbase, staff, or members user base.
  • might be a speical case where front-end apps session is cleared and replced by member session upon elevation when member logs in.
  • one user object per app per webclient at anyone time (as opposed to trying to reference a person with a guest user AND a member user - that's too complicated)
  • one session per user per app (namespaced to avoid conflicts with other apps that they may be logged into on that domain) - (as opposed to trying to simultaneously refer to 'the person using it' with a guest session AND a member session. again, that's too complicated)

ok i am starting to ramble....but you get the idea. Don't let the Zend_Auth+Zend Db tutorials that you see sway your own model. they are just simplified examples.

nuff said

JW
A: 

I have a few questions about this piece of code

    $auth = Zend_Auth::getInstance();
    $identity = new stdClass();
    $identity->user_pk = $user->getPrimaryKey();
    $identity->user_name = $user->getName();
    $identity->role = $user->getRole(); // select * from user_role where user_pk=xxx
    $auth->getStorage()->write($identity);

    $identity = Zend_Auth::getInstance()->getIdentity();

Are user_pk, user_name and role stored as cookies? Will someone that makes a cookie with the role-name able to access the secured parts of the websites? Shouldn't a password (with md5-encryption) be part of the identy as well so when can verify username and password with each request?

murze