Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Allow for flexible configuration of authorization logic within the framework. The authorization checks should be well exposed (i.e. visible). It should be straight forward to add new checks, or modify existing ones. It should be possible to use GaP as the authorization engine, alternative engines and their combination.

Proposed approach

...

Implementation

The implementation uses ACEGI declarative authorization proxy factories, providing implementations necessary to support a voter class implementation (PermissionVoter) that talks to GaP back-end. PermissionVoter is configured with a permission target resolver (a bean whose task is to identify permission target from either configuration attributes or the arguments of the intercepted method call).

Example

Here is a modified example of using ACEGIs' MethodSecurityInterceptor to configure authorization checks for checking permissions on performing various actions with portlet definition (or its derivatives, like portlet window)'s an example of how ACEGI constructs can be used together with a PermissionVoter to protect a mock portlet definition registry:

Code Block
xml
xml
<!-- the registry being protected -- authorization check proxy factory targeting key methods that handle portlet definitions>
<bean id="mockPortletDefinitionRegistry" class="org.jasig.portal.security.acegi.MockPortletDefinitionRegistry"/>

<!-- the security interceptor that in this case is configured to protect portlet definition regisrty calls -->
<bean id="portletEntitySecurityportletDefinitionSecurityInterceptor" class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
    <property name="authenticationManager"><ref beanlocal="authenticationManagerauthentication"/></property>
    <property name="portletDefinitionDecisionManageraccessDecisionManager"><ref beanlocal="accessDecisionManagerportletDefinitionAccessDecisionManager"/></property>
    <property name="objectDefinitionSource">
        <!-- Below is a mapping of intercepted methods to configuration attributes that will be passed to the voter
             In this case "remove*" and "create*" methods  <value>are configured with the activity attribute and the target
             org.jasig.portal.portlet.rendering.MultithreadedPortletRenderingModel.*=ACTIVITY_RENDER(portlet definition id) is picked up by the resolver from the method call arguments. The update* method
             is configured with both activity and target (prefix for targets is PORT_ID in this case, see target resolver
             configuration below) - in this case target resolver will pick up the target from the config attribute
             instead of looking at the arguments passed to the method.
        -->
        <value> 
            org.jasig.portal.portlet.registry.general.IPortletDefinitionRegistry.createupdate*=ACTIVITY_CREATE_UPDATE,PORT_ID.*
            org.jasig.portal.portlet.registry.general.IPortletDefinitionRegistry.getremove*=ACTIVITY_RENDERDELETE
            org.jasig.portal.portlet.registry.general.IPortletDefinitionRegistry.updatecreate*=ACTIVITY_UPDATECREATE
        </value>
    </property>
</bean>

<!-- access decision manager for checkingportlet permissions on portlet definitionsdefinition access -->
<bean id="portletDefinitionDecisionManagerportletDefinitionAccessDecisionManager" class="org.acegisecurity.vote.UnanimousBased">AffirmativeBased">
    <property name="allowIfAllAbstainDecisions">
        <value>false</value>
    </property>
    <property name="decisionVoters">
        <list>
            <!-- GAP voter -->
            <bean class="org.jasig.portal.security.acegi.PermissionVoter">
                <property name="targetResolver">
                    <ref local="portletDefinitionTargetResolver"/>
                </property>
                <property name="permissionOwner" value="UP_FRAMEWORK"/>
                <property name="framework"authorizationService">
                    <ref local="authorizationService"/>
                </property>
                <property name="activityPrefix" value="ACTIVITY_"/>userController">
                    <ref local="userController"/>
                </property>
                <property name="activityPrefix" value="targetResolverACTIVITY_"/>
            </bean>
        </list>
    </property>
</bean>

<!-- permission target resolver for portlet definition id targets -->
<bean id="portletDefinitionTargetResolver" class="org.jasig.portal.security.acegi.PortletDefinitionIdResolver"/>
    <property name="targetPrefix" value="PORT_ID."/>
    <property </property>
            name="allowMissingTarget" value="true"/>
</bean>

<!-- proxy configuration: this can be used to protect multiple beans, but in this case only mock registry is proxied -->
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
    <property name="authorizationServicebeanNames">
        <value>mockPortletDefinitionRegistry</value>
    </property>
    <ref<property beanname="authorizationServiceinterceptorNames"/>
        <list>
    </property>        <value>portletDefinitionSecurityInterceptor</value>
 </bean>       </list>
    </property>
    <property name="proxyTargetClass" value="true"/>
</bean>

Suggested use pattern

The PermissionVoter is provided with configuredwith the permissionOwner property, and a helper bean that can resolve permission targets (targetResolver). The example above suggests that a given access decision manager should be associated with a single owner and a single target type. This should make configuration more transparent and more efficient. For instance, a different decision manager, portletDeploymentDecisionManager, would be created to check authorization to publish portlets.

...