2009年9月1日星期二

Re: [fw-mvc] MVC integration of Zend_Acl

-- Seth Atkins <satkins@nortel.com> wrote
(on Tuesday, 01 September 2009, 02:01 AM -0500):
> >As I noted earlier, I personally like to put my ACLs with my service
> layer. This means that I'm actually >executing my action before I find
> out if the user has the ability to do something -- probably your worst
> >nightmare.
>
> True, that wouldn't be my preference. The analogy I would make is that
> it is like a file system retrieving the file, reading it, and even
> opening it, just to find that permission isn't granted and averting
> showing it to the display. Not that there might not be advantages, but
> to extend the analogy a bit further, in some cases, it is also like
> executing a bash script that alters other files or processes just to
> find out later, when output is being processed that execute permission
> wasn't allowed in the first place.

I find this logic a bit flawed. If you consider a web application is
like a GUI interface, then there are several layers of abstraction
between the GUI interaction and checking the file system -- and that
analogy is more relevant with an MVC paradigm (MVC was built to
facilitate GUIs, after all).

Regardless, there are many ways to look at web applications and ACLs.
Your points may be valid for some approaches, Thierry's for other
approaches, and the route I suggest for still others. It depends on what
you are architecting your site for.

More below.

> The point is that in some applications, where actions alter the
> database, you can't afford to have access checking performed later,
> because the damage would already have occurred by the time you ever
> checked! It isn't a matter of preference, rather an imperative.

Then you misunderstand how the service layer works.

My service layers are simply classes defining the public API of the
application. The controller actions call these methods, but really do
very little work; all they do is pass input to the service layer and
pass the output on to the view (there may be a little bit of logic
involved, but very minimal). The service layer encapsulates all
interactions with the domain entities, including persistence (database
access); as such, there is nothing outside the service layer itself that
can alter the database.

In the service layer methods, if ACLs are necessary, a check is
performed immediately, prior to any other activity. If the check fails,
an exception is raised -- I create an "Unauthorized" or similar
exception type, and then check for that in my ErrorController so I can
raise a 401 status.

The point, however, is that no database or web service call has occurred
yet. There's nothing to be damaged, and thus no imperative to move ACLs
higher in the stack. I gain a key benefit, however: my ACLs work even
when no longer executed within my controllers (which is important if you
want to re-expose the application as a web service).

> In other applications where actions mostly relate to just viewing
> information, it doesn't matter so much where access is checked as long
> as it is any time before data is sent to the client browser. And in
> this realm, I wouldn't dare suggest that there is ONE right answer, or
> even that my view is better, since I recognize my inexperience.
>
>
> --Seth
>
> -----Original Message-----
> From: Matthew Weier O'Phinney [mailto:matthew@zend.com]
> Sent: Friday, August 28, 2009 1:23 PM
> To: fw-mvc@lists.zend.com
> Subject: Re: [fw-mvc] MVC integration of Zend_Acl
>
> -- Seth Atkins <satkins@nortel.com> wrote (on Friday, 28 August 2009,
> 12:52 PM -0500):
> > Two main comments from my part. The first is a fairly open ended
> > question I can't answer for you. While an action helper may fit your
> > needs very well, IMHO, a successful integration is one which serves
> > many common approaches and is the least limited implementation. For
> > example, some of the comments so far have related to treating actions
> > as resources. Many people see actions as privileges on resources, and
> > one common view of what a resource is is a controller resource. If
> > this is such a person's view on the subject, an action helper seems
> > fairly limited since you are dispatching to a controller before you
> > actually check resource access. I'd rather back things up a few steps
> > and check before any particular resource is called. But that is my
> > opinion, and I do know I'm not alone there. I believe, and correct me
> > if I am wrong here, but the action helper preDispatch() method is
> > called after the controller init(), which is also after any controller
>
> > preDispatch() method, which is also after any plugin preDispatch
> methods.
>
> Close, but not quite. Order is:
>
> front controller plugin preDispatch
> action helper init()
> controller init()
> action helper preDispatch()
> controller preDispatch()
>
> The only place you can circumvent is at the plugin preDispatch(); if you
> call _forward() later, it will continue to execute through the
> controller preDispatch(); the only thing skipped will be the actual
> controller action (and postDispatch, of course).
>
> > Seems to me a lot has happened before you ever checked to see if any
> > of that should have happened in the first place.
> >
> > I am less familiar with all the things you can do with an action
> > helper and how one might wrest it to do your will. My understanding of
>
> > the ZF plugin architecture is more detailed since I have spent some
> > time tracing through the code, how plugins are called, when, etc.
> > Anyway, I know that plugins can do exactly what I want, but I'm less
> > sure that an action helper would fit my needs.
>
> What action helpers provide you is integration with the action
> controller. Basically, you can place metadata or methods in your action
> controllers that the action helpers can then query (or manipulate) to do
> things.
>
> Some examples of such integration:
>
> * ViewRenderer: sets the view object, as well as renders the view
> script postDispatch() based on the action executed
>
> * ContextSwitch/AjaxContext: if certain properties are set in the
> action controller, will query those to determine if a context was
> invoked, and, if so, change the view script rendered (as well as
> potentially inject response headers)
>
> Basically, what action helpers do is make it easier to place the context
> for a decision close to the decision point.
>
> However, as you note, there may be a performance cost associated with
> this.
>
> > The second comment is that plugins are called before ANY dispatching
> > (of any sort) occurs. Not even a controller init() method has been
> > called yet. I can create one plugin, set it up in Zend_Application,
> > and all my ACL code is in one place, once line of code to setup the
> > plugin, and I'm done. The plugin is post routing, so it has the
> > filtered request object to work from. You can load your rules and then
>
> > feed isAllowed your controller or action name, or whatever criteria
> > you want. If you want actions to be resources, fine. If you want
> > controllers to be resources and actions privileges, fine.
> >
> > And best of all, a plugin can alter the request object before
> > dispatching occurs. So I can actually redirect without "redirecting",
> > if you know what I mean, in response to access being denied.
> >
> > To sum up, I don't think an action helper would be an implementation
> > that I would personally want to use.
>
> You have valid points. The points in the proposal are also valid. They
> are very different approaches, however, and there are different
> ramifications involved with both. In your situation, you get good
> execution speed -- but at the cost of having to update ACLs and
> controllers separately. In the approach proposed, your ACLs are part of
> your application structure, making maintenance easy -- but you lose some
> performance.
>
> As I noted earlier, I personally like to put my ACLs with my service
> layer. This means that I'm actually executing my action before I find
> out if the user has the ability to do something -- probably your worst
> nightmare.
>
> However, what this affords me is the ability to re-use my service layer
> for web services -- I can create a service proxy object that I attach to
> Zend_XmlRpc_Server, Zend_Json_Server, Zend_Amf_Server, etc -- and my
> ACLs continue to work as expected. I don't have to do anything different
> whatsoever.
>
> > I have many modules, many controllers, many actions, and while, yes, I
>
> > could write one action helper and call it from anywhere, I'd really
> > rather not have to write 50 lines of code to just to call it from each
>
> > controller I happen to have. And I'd rather not instantiate a
> > controller that a person doesn't have access to in the first place.
> > Just my 2 cents.
>
> Again, as noted above: there are different approaches. Use the one that
> suits your application and/or programming needs.
>
>
> > -----Original Message-----
> > From: jThierry [mailto:thierry@jossermoz.net]
> > Sent: Thursday, August 27, 2009 9:44 PM
> > To: fw-mvc@lists.zend.com
> > Subject: [fw-mvc] MVC integration of Zend_Acl
> >
> >
> > Hi all,
> >
> > I've been working on a component to realise the MVC integration of
> > Zend_Acl which is different from the proposal
> > (http://framework.zend.com/wiki/pages/viewpage.action?pageId=39025)
> > that seems to be on hold.
> >
> > I'm using an action helper the perform the checks at pre dispatch time
>
> > on controllers implementing Zend_Acl_Resource_Interface instead of a
> > plugin and am wondering if there's any underlying reason that would
> > encourage the use of a plugin.
> >
> > I would really much appreciate your feedback on the action helper
> > approach.
> >
> > The code can be found there: http://code.google.com/p/oolala/
> >
> > Thanks,
> >
> > Thierry

--
Matthew Weier O'Phinney
Project Lead | matthew@zend.com
Zend Framework | http://framework.zend.com/

没有评论: