[
http://jira.jboss.com/jira/browse/JBSEAM-1009?page=all ]
Leo Baschy updated JBSEAM-1009:
-------------------------------
Attachment: weaker-explicit-security.patch
New patch file name replaces old file name:
weaker-explicit-security.patch
This got bigger now, but it fulfills a purpose: Allow good practical security
configurations with greater certainty of correctness, partially due to terseness.
Backwards compatibility was a major design factor too.
Illustrated by a use example from our main project. In real use though we are using
.page.xml files (except wildcards) instead of so many page elements.
Security items to look for in the example are:
1) weaker-explicit-security="true" Without that Seam would be the way it used
to be and you can think through which parts then wouldn't work.
2) By wildcard "*" for the whole site some security is being established.
2a) login-required="true" means no viewing if not logged in.
2b) <restrict>#{s:hasPermission('adminStuff', 'basic',
null)}</restrict> means unless set otherwise, only those with permission to do
adminStuff can see pages.
Note that any directory added anywhere does have at least some security then. You
can't "forget" adding security for a new directory.
Later in project development, with other URLs set, it was decided we needed pages for
consumers/subscribers. Hence
3) By wildcard "/consumer/*" different security is being established.
3a) login-required="true" wasn't really necessary to repeat, but it is ok.
3b) <restrict>#{s:hasPermission('subscriberStuff', 'basic',
null)}</restrict> is in effect instead (!) of the adminStuff.
Point is that directory is for consumbers/subscribers. The rest of the site is for
admins, but this directory would not benefit from the "old" Seam way of
requiring both restrict tests to pass.
Then we came up with multi-page login. Depending on where you're trying to go to you
get a different login page. One for admins, one for consumers/subscribers.
There only being one login-view-id we have to dispatch. You'll recognize that only
the login-view-id itself is exempt from login-required. Hence
4) Several specific pages for login and registration all have an explicit
login-required="false".
Different than the "old" Seam way that explicit login-required="false"
is effective for that page or wildcard.
4a) And because these pages with explicit login-required="false" don't have
an explicit <restrict> themselves, the restrict from any wildcard for them has been
overridden too.
A restrict would require login. If needed it can be put in explicitely and wouldn't
be overridden, but what's the intention there? Useless case, self-contradicting
settings.
Note that this gives you the freedom to make any content at any URL available with
different <restrict> or even without login, even when the rest of the site remains
tight.
Security now is a function of your settings, not unduly limited by relative location
logic.
If you are paranoid you can have a script make sure there are no changes to occurrences of
login-required and restrict.
5) Not shown in the example there is <restrict>none</restrict>, which allows
to override any restriction from a less specific wildcard.
For some time we needed to accompany each login-required="false" with a
<restrict>none</restrict>, when that got old we implemented 4a).
The example:
<pages login-view-id="/login/required.xhtml"
weaker-explicit-security="true">
<page view-id="*" login-required="true">
<restrict>#{s:hasPermission('adminStuff', 'basic',
null)}</restrict>
</page>
<page view-id="/consumer/*" login-required="true">
<restrict>#{s:hasPermission('subscriberStuff', 'basic',
null)}</restrict>
</page>
<page view-id="/login/required.xhtml" login-required="false">
<action execute="#{loginDispatcher.doDispatch}" />
<navigation from-action="#{loginDispatcher.doDispatch}">
<rule if-outcome="consumer">
<redirect view-id="/consumer/login.xhtml" />
</rule>
<rule>
<redirect view-id="/all/login.xhtml" />
</rule>
</navigation>
</page>
<page view-id="/consumer/login.xhtml" login-required="false">
<action execute="#{consumerLogin.tryWithoutForm}" />
<navigation from-action="#{consumerLogin.tryWithoutForm}">
<rule if="#{identity.loggedIn}">
<redirect view-id="/consumer/main/menu.xhtml" />
</rule>
<rule if-outcome="new mdn">
<redirect view-id="/consumer/registration/new.xhtml" />
</rule>
</navigation>
<navigation from-action="#{identity.login}">
<rule if="#{identity.loggedIn}">
<redirect view-id="/consumer/main/menu.xhtml" />
</rule>
</navigation>
</page>
<page view-id="/consumer/registration/new.xhtml"
login-required="false">
<navigation from-action="#{subscriberHome.persist}">
<rule if-outcome="persisted">
<end-conversation />
<redirect view-id="/consumer/main/menu.xhtml" />
</rule>
</navigation>
</page>
<page view-id="/all/login.xhtml" login-required="false">
<navigation from-action="#{identity.login}">
<rule if="#{identity.loggedIn}">
<redirect view-id="/admin/home.xhtml" />
</rule>
</navigation>
</page>
</pages>
Then there are some implementation details we'd rather not have had to deal with.
To get it out of the way let's mention we don't cause that problem: If there
isn't a login-required but there is a restrict then an exception is thrown that then
causes some afterRender to be called when there wasn't a call to beforeRender.
More interestingly, there is some interaction between dom4j and DTDs. It goes like this:
When pages.xml or a page.xml mentions on of the DTDs that says
<!ATTLIST page login-required (true|false) "false">
then it appears to be impossible to tell via dom4j whether login-required has been set
explicitely. If it hasn't been set it doesn't report null, but "false".
No way to find out what is in the DOM tree.
The effect would be when lacking a explicit login-required then erroneously working like
login-required="false" - instead of inheriting from a less specific wildcard - a
very bad bug.
That problem goes away when having a DTD with
<!ATTLIST page login-required (true|false) #IMPLIED>
or no (!) DTD mentioned.
Problematic DTDs include at least "-//JBoss/Seam Pages Configuration DTD
1.2//EN" "http://jboss.com/products/seam/pages-1.2.dtd".
The current workaround implemented is if (and only if)
weaker-explicit-security="true" then rejecting (log.error and RuntimeException
with very clear text) those old DTDs if used. Does allow use of none or newer.
A second workaround currently coded into the patch, but relatively easy to replace, is to
enforce use of same DTD (or none at all) for pages.xml and all whatever.page.xml on whole
site. That one could be replaced with just rejecting the old DTDs but not caring whether
all are the same. I'll be happy to make that change and test it, but I didn't
want to sit on this patch any longer before submitting it.
optionally login-require in a more specific page should be able to
override a wildcard login-require
----------------------------------------------------------------------------------------------------
Key: JBSEAM-1009
URL:
http://jira.jboss.com/jira/browse/JBSEAM-1009
Project: JBoss Seam
Issue Type: Patch
Components: Security
Affects Versions: 1.2.0.GA
Environment: all
Reporter: Leo Baschy
Assigned To: Shane Bryzak
Attachments: may-override-login-required.patch,
may-override-login-required.patch, weaker-explicit-security.patch
This should be optional to switch on, so no one's existing expectations of security
get broken.
The point is about having a generic wildcard <page view-id="*"
scheme="http" login-required="true"> to secure the whole site, and
then allowing specific pages or specific wildcards to have
login-required="false". E.g. for a registration (with preview) section as one
cannot be logged in if one isn't registered yet.
Some may suggest instead forcing pages into dedicated secure and not-secure directories,
but in reality if there are multiple reasons to force pages into directories different
ways (security, hyperlink management, publishability of URLs, etc.), one cannot serve all
of them.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://jira.jboss.com/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira