On Sat, May 24, 2008 at 11:11 AM, Andrea Jahn <[EMAIL PROTECTED]> wrote:
>
>
>
>
> Hi,
>
> No I think(hope) I got it. I've implemented an example based on my earlier
> created SecureLink example.
> There's a DataView. The items area Locations. For each item a delete link is
> created. Users with global
> action permission can see and click the delete link for every Location. A
> user with action location
> can only see and click the delete link for Locations, which are allowed for
> that user.
>
>
> LocationListPage.java:
> ----------------------------
> protected void populateItem(final Item item) {
> final Location location = (Location) item.getModelObject();
>
> item.add(new Label("name", location.getName()));
>
>
> // Delete link for testing Swarm
> SecureLink deleteLink = new SecureLink("deleteLocation") {
> private static final long serialVersionUID = 1L;
>
> public void onClick() {
> return;
> }
> };
> deleteLink.setSecurityCheck(new LocationDataSecurityCheck("deleteLocation",
> location.getName()));
>
> item.add(deleteLink);
> // end Delete link for testing Swarm
>
> }
> }
>
>
> LocationDataSecurityCheck.java
> ------------------------------
> public class LocationDataSecurityCheck extends DataSecurityCheck
> {
> private static final long serialVersionUID = 1L;
>
> private String locationName;
>
> /**
> * Constructs a new check.
> */
> public LocationDataSecurityCheck(String securityId, String name)
> {
> super(securityId);
> locationName = name;
> }
>
> /**
> * @see
> org.apache.wicket.security.checks.AbstractSecurityCheck#isActionAuthorized(org.apache.wicket.security.actions.WaspAction)
> */
> public boolean isActionAuthorized(WaspAction action)
> {
> WaspAction combinedAction = null;
> WaspAction globalAction, locationAction;
> ActionFactory factory = getActionFactory();
>
> globalAction = factory.getAction(GlobalAction.class);
> combinedAction = action.add(globalAction);
>
> // global: so everything is allowed for the user independent of the location
> if (super.isActionAuthorized(combinedAction))
> return true;
>
> locationAction = factory.getAction(LocationAction.class);
> combinedAction = action.add(locationAction);
>
> // location: it must be checked, if the user has rights for that location
> if (super.isActionAuthorized(combinedAction))
> if (locationName.equals("dummy"))
> return true;
>
> // no permission set
> // or location permission is set, but not sufficient for the location
> return false;
>
> }
>
> /**
> * Checks if the user is authenticated for this component.
> *
> * @see ISecurityCheck#isAuthenticated()
> * @see WaspAuthorizationStrategy#isComponentAuthenticated(Component)
> */
> public boolean isAuthenticated()
> {
> return super.isAuthenticated();
> }
>
> }
>
>
> policy file:
> ------------
> // Location list page - Delete link only for allowed locations
> permission ${DataPermission} "deleteLocation", "enable, location";
>
> or:
> ---
> // Location list page - Delete link for all locations
> permission ${DataPermission} "deleteLocation", "enable, global";
Yep looks good.
>
> ------------------------------------------------------------------------------------------------------------------------------------
>
>
>
> We have a lot of WebMarkupContainers and it is not clear now, which would be
> necessary to be secure in the future.
> So I tried to use the denial strategy (and it works). Every secure container
> is allowed, it has to be declined in the policy file.
> (every container can be a secure container at programming time and the
> programmer has not to care about the permissions).
>
>
> SecureWebMarkupContainer.java:
> -------------------------------------------
> public class SecureWebMarkupContainer extends WebMarkupContainer implements
> ISecureComponent
> {
>
> private static final long serialVersionUID = 1L;
>
> /**
> *
> * Constructor
> *
> * @param id
> */
> public SecureWebMarkupContainer(String id)
> {
> super(id);
> setSecurityCheck(new DenialContainerSecurityCheck(this));
> }
>
> /**
> *
> * @see
> org.apache.wicket.security.components.ISecureComponent#getSecurityCheck()
> */
> public ISecurityCheck getSecurityCheck()
> {
> return SecureComponentHelper.getSecurityCheck(this);
> }
>
> /**
> *
> * @see
> org.apache.wicket.security.components.ISecureComponent#isActionAuthorized(java.lang.String)
> */
> public boolean isActionAuthorized(String waspAction)
> {
> return SecureComponentHelper.isActionAuthorized(this, waspAction);
> }
>
> /**
> *
> * @see
> org.apache.wicket.security.components.ISecureComponent#isActionAuthorized(WaspAction)
> */
> public boolean isActionAuthorized(WaspAction action)
> {
> return SecureComponentHelper.isActionAuthorized(this, action);
> }
>
> /**
> *
> * @see
> org.apache.wicket.security.components.ISecureComponent#isAuthenticated()
> */
> public boolean isAuthenticated()
> {
> return SecureComponentHelper.isAuthenticated(this);
> }
>
> /**
> *
> * @see
> org.apache.wicket.security.components.ISecureComponent#setSecurityCheck(org.apache.wicket.security.checks.ISecurityCheck)
> */
> public void setSecurityCheck(ISecurityCheck check)
> {
> SecureComponentHelper.setSecurityCheck(this, check);
> }
>
> }
>
>
>
> DenialContainerSecurityCheck.java:
> --------------------------------------------
>
>
> public class DenialContainerSecurityCheck extends ContainerSecurityCheck
> {
> private static final long serialVersionUID = 1L;
>
> /**
> * Constructor
> *
> * @param component the container
> */
> public DenialContainerSecurityCheck(MarkupContainer component)
> {
> super(component);
> }
>
> /**
> * Turns around the security check.
> *
> * @see
> org.apache.wicket.security.checks.ComponentSecurityCheck#isActionAuthorized(org.apache.wicket.security.actions.WaspAction)
> */
> public boolean isActionAuthorized(WaspAction action)
> {
> return !super.isActionAuthorized(action);
> }
>
> }
You could use the InverseSecurityCheck, it does exactly the same only
for any given security check.
>
> MyApplication.java:
> ------------------
> protected void setUpHive()
> {
>
> factory.setAlias("DenialComponentPermission",
>
> "org.apache.wicket.security.hive.authorization.permissions.ComponentPermission");
>
> }
>
>
> policy file:
> ------------
> permission ${DenialComponentPermission}
> "${front}.ProductAreaListPage:resultHiddenPanel", "inherit, render";
>
>
> I made an additional alias for the ComponentPermission, so it is clearer in
> the policy file that the permission
> is in reality a declination.
> We would have to pay attention on the inherit action of the page (page
> allowed, panel not).
Yes but also the fact that you use a different alias is only a fake
sense of clearity/security. For the system this is still a permission,
if you want to deny something you don't include it in the policy file.
Any other check then your DenialContainerSecurityCheck is going to see
this as a permission. While this will probably work out, there might
be corner cases where this will behave different from what you expect.
Imo it is very easy to either replace the WMC with a SWMC if it is
decided that it should be secure. Or simply make them all secure and
train your programmers to add 1 line to the policy file.
>
>
> Is it right, that the method isActionAuthorized() within the
> SecureWebMarkupContainer is never called,
> because always the method of the SecurityCheck is used ?
Yest the strategy always enters through the securitycheck, it could
use the isActionAuthorized but now the strategy can do a nullcheck on
the securitycheck so the implementations don't have to. Basicaly the
isAuthorized/Authenticated methods are there for easy access for the
programmer.
> ------------------------------------------------------------------------------------------------------------------------------------
>
> Now I have successfully tested authorization management in a lot of different
> situations and we have decided to use Wasp/Swarm for our
> appication (where we need a very flexible rights management for the users).
Good to hear :)
>
> For the first release I think we will store different User roles in the
> database and those user roles will correspond to the principals
> within the policy file.
That is certainly possible, but if you want really flexible you let
your roles have a set of principals. that way you can give far more
finegrained control.
I think in our app we have over 1000 principals. It will also save you
on duplicating permissions that are shared by multiple roles. Anyway
just a suggestion :)
> But in the future we would like to store the permissions also in the database
> and administer them online. Am I right, that I will have to
> implement our own HiveFactory, which reads the data from the database and
> creates the hive ?
Correct.
Maurice
>
> Andrea
>
>
>
> *Von:* [email protected]
> *Gesendet:* 22.05.08 23:08:55
> *An:* [email protected]
> *Betreff:* Re: filter for data in security layer
>
>
>
> I am not sure i follow you.
>
> According to the log the user does not have the datapermission for the
> dropdown.
>
>> I tried to set the permissions like in the explanation below, but that
>> didn't work:
>>
>> // Welcome page
>> permission ${ComponentPermission} "${front}.Welcome", "inherit, render,
>> global";
>> permission ${ComponentPermission} "${front}.Welcome", "enable, global";
>
> What is not working?
>
>
> In general adding custom actions to your pages is only useful if the
> page has a securitycheck that actually checks for those actions. In
> the case of a welcome page that is probably overkill but for a page
> showing for example customer info it would be very useful to check if
> the user has global permissions and thus can see any user or local
> permissions and this only is the customer is affiliated with one of
> his locations. Such a check could be implemented like this.
> public boolean isActionAuthorized(WaspAction action)
> {
> WaspAction combined = null;
> WaspAction additional;
> ActionFactory factory = getActionFactory();
> additional = factory.getAction(Global.class);
> combined = action.add(additional);
> //wrapped is another isecuritycheck like a component- or classsecuritycheck
> if (wrapped.isActionAuthorized(combined))
> return true; //global so everything is allowed
> additional = factory.getAction(Location.class);
> combined = action.add(additional);
> if (wrapped.isActionAuthorized(combined))
> return verifyCustomerLocationMatchesUserLocations(someCustomer, theUser);
> return false;
> }
> The custom security check in the examples simply overrides an existing
> check where this check could extend AbstractSecurityCheck but the
> principal is the same. You need to check your custom actions yourself.
>
> Not sure if that at all answers your question.
>
> Maurice
>
>>
>> Debug logging:
>> 2008-05-22 14:47:57,515 DEBUG
>> org.apache.wicket.security.hive.BasicHive.addPrincipal(BasicHive.java:111) -
>> Adding
>> org.apache.wicket.security.hive.authorization.permissions.ComponentPermission
>> "xxx.yyy.zzz.front.Welcome" "access, render, enable, location, global" to
>> everybody
>> 2008-05-22 14:47:57,515 DEBUG
>> org.apache.wicket.security.hive.BasicHive.addPrincipal(BasicHive.java:111) -
>> Adding
>> org.apache.wicket.security.hive.authorization.permissions.ComponentPermission
>> "xxx.yyy.zzz.front.Welcome" "access, inherit, render, location, global" to
>> everybody
>>
>> 2008-05-22 14:48:13,046 DEBUG
>> org.apache.wicket.Component.render(Component.java:2284) - Begin render
>> [MarkupContainer [Component id = selectLocation, page =
>> xxx.yyy.zzz.front.Welcome, path =
>> 1:formLocation:selectLocation.DropDownChoice, isVisible = true, isVersioned
>> = false]]
>> 2008-05-22 14:48:13,046 DEBUG
>> org.apache.wicket.security.hive.BasicHive.hasPermission(BasicHive.java:224)
>> - Subjects[HashKey: -1185945692, sortOrder 0 = [EMAIL PROTECTED]
>> [mailto:[EMAIL PROTECTED] does not have or implies
>> org.apache.wicket.security.hive.authorization.permissions.DataPermission
>> "LocationListModel" "global"
>>
>> Andrea
>>
>> -----------------
>> On Sun, May 18, 2008 at 7:26 PM, Igor Vaynberg <[EMAIL PROTECTED]
>> [mailto:[EMAIL PROTECTED]> wrote:
>>> something like this should probably be filter inside the database not
>>> by some external filter which forces you to load the entire dataset.
>>
>> No that would be foolish, but that wasn't suggested.
>>
>>>
>>> -igor
>>>
>>> On Sun, May 18, 2008 at 9:39 AM, Andrea Jahn <[EMAIL PROTECTED]
>>> [mailto:[EMAIL PROTECTED]> wrote:
>>>>
>>>>
>>>>
>>>>
>>>> Hi,
>>>>
>>>> in our application locations are administered. A user has only rights on
>>>> some of the locations, e.g. Munich, Berlin. He should be able to select
>>>> one of the allowed locations in a selection box. Then on the different
>>>> pages all data are depending on the actually selected location. For
>>>> example a DataView shows only the items, which belong to this location.
>>>>
>>>> Could Swarm support data filtering ?
>>
>> Yes, especially in 1.3.1 this is a bit cleaner dependency wise. But
>> there is no out of the box solution as there are lots of framework
>> combinations possible. So get ready for some heavy duty programming :)
>>
>>>>
>>>> I found the following related message.
>>>>
>>>> http://markmail.org/message/hb42u5xj7xlvumm7
>>>> [http://markmail.org/message/hb42u5xj7xlvumm7]
>>>> [http://markmail.org/message/hb42u5xj7xlvumm7] (subsection4)
>>>>
>>>> I like the idea, that the dataproviders get some filters (only the data
>>>> which are needed should be read from the database), but where should I
>>>> store the filters for the actual selected location in the security layer ?
>>>>
>>>> Perhaps does someone know examples for that issue (using Wicket, Spring
>>>> and Hibernate) ?
>>
>> Not aware of any examples out there, but here is what we did,
>> customized to your situation for as far as i understand it :)
>> Suppose we have a searchpage with some filter criteria including a
>> dropdown for the location. The data in this dropdown is filtered by
>> the permissions the user has for this page. If he has "global"
>> permissions the dropdown contains all locations. otherwise it only
>> contains locations assigned to this user. The user is not required to
>> select a location, if he does that location will be used but if he
>> clears the selection the search will be over all allowed locations.
>> clicking a row in the search results will bring him to a another page
>> from where he can navigate to other pages to see different data. These
>> pages can have different permissions as the search page. for example a
>> user has "global" search and report permissions but only "location"
>> permissions for administrative tasks.
>>
>> Note that if all pages behind the searchpage have the same permissions
>> you might be able to skip using custom actions.
>>
>> To make the concept of locations clear to wasp you have to define your
>> own custom actions (see the actions section in
>> http://wicketstuff.org/confluence/display/STUFFWIKI/Getting+started+with+Swarm
>>
>> [http://wicketstuff.org/confluence/display/STUFFWIKI/Getting+started+with+Swarm]
>> and the end about changes in 1.3.1)
>> Might i suggest a "global" and a "location" action. where the global
>> action could (probably should) imply the location action. Note you do
>> not create an action for each location you have just 1 action called
>> "location" the code will later decide which location(s) that will be.
>>
>> Because you now want to grant global or location permissions you will
>> need to duplicate each principal making sure each has a different
>> name, i suggest prefixing the principals with either global or
>> location. So this will give you
>>
>> grant principal org.MyPrincipal "global.search.something"
>> {
>> permission ${ComponentPermission} "org.SearchSomethingPage",
>> "inherit, render, global";
>> permission ${ComponentPermission} "org.SearchSomethingPage", "enable,
>> global";
>> };
>> grant principal org.MyPrincipal "location.search.something"
>> {
>> permission ${ComponentPermission} "org.SearchSomethingPage",
>> "inherit, render, location";
>> permission ${ComponentPermission} "org.SearchSomethingPage", "enable,
>> location";
>> };
>>
>> (On a side note: if you have a lot of principals or extra custom
>> actions this can become quite a pain to maintain, but there are hooks
>> to make this easier)
>>
>> For the location list model of your dropdown you can use a LDM
>> implementing SwarmModel where the load will look something like this
>>
>> if (isAuthorized(null, getActionFactory().getAction(Global.class)))
>> //return all locations
>> else
>> // return user locations
>>
>> Use the various isModel..... methods on WaspAuthorizationStrategy to
>> implement SwarmModel.
>> No need to add an ISecurityCheck to the component itself as swarm will
>> detect the secure model and use that instead. Don't forget to add a
>> DataPermission to your principals with the appropriate actions.
>>
>> The selection model for the dropdown could be any model it just needs
>> to update a filter bean which you will pass to your dao, because the
>> selection might be null the filter also needs to know about which
>> locations are allowed, just use the list model for that. Then in your
>> dao you need to either use the selected location or the list to return
>> the search results.
>>
>> Maurice
>>
>>>>
>>>> Thanks in advance
>>>> Andrea
>>>>
>>>>
>>>>
>>
>>
>>
>> EINE FÜR ALLE: die kostenlose WEB.DE-Plattform für Freunde und Deine
>> Homepage mit eigenem Namen. Jetzt starten! *http://unddu.de/[EMAIL
>> PROTECTED] [http://unddu.de/[EMAIL PROTECTED]
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]
>
>
>
>
>
>
> EINE FÜR ALLE: die kostenlose WEB.DE-Plattform für Freunde und Deine
> Homepage mit eigenem Namen. Jetzt starten! *http://unddu.de/[EMAIL PROTECTED]
> [http://unddu.de/[EMAIL PROTECTED]
>
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]