WebFacetsHOW-TOsAuthentication
YourKit Java Profiler |
AccessControlAccess Control (also referred to as Authorization) is the fact of allowing or disabling access to some resources for some roles. This page describes how this can be handled as well using the Profiles Graph concept. For now, the solution is fully Stripes-based, since I personnally use this framework and had authorization requirements in a project using both Stripes and JFacets. In this context, securing the app means "allowing some profiles to invoke ActionBean events or not". Of course, integration with other technologies should be possible as well... The Stripes Security ExtensionA Stripes user recently contributed a pretty cool extension that allows declarative Access Control, via specific annotations. This module simply extends the Stripes filter, and only requires you to implement a SecurityManager for your application. Secured ActionBeansHere under is a self-explanatory example of a secured ActionBean : package reflectdemo.actions; import net.sourceforge.stripes.action.Resolution; import net.sourceforge.stripes.action.SimpleMessage; import net.sourceforge.stripes.action.UrlBinding; import net.sourceforge.stripes.security.action.Secure; @UrlBinding("/ACLTest.action") public class ACLTestActionBean extends BaseActionBean { /** * EventA : no security restrictions (all users, even unauthenticated) */ public Resolution eventA() { setMessage("Event A invoked"); return getContext().getSourcePageResolution(); } /** * EventA : only authenticated profiles (everything inerits root_profile) */ @Secure(roles="root_profile") public Resolution eventB() { setMessage("Event B invoked"); return getContext().getSourcePageResolution(); } /** * EventA : only "standard_role" profile (and its childs) */ @Secure(roles="standard_role") public Resolution eventC() { setMessage("Event C invoked"); return getContext().getSourcePageResolution(); } /** * EventA : only "admin_role" profile (and its childs) */ @Secure(roles="admin_role") public Resolution eventD() { setMessage("Event D invoked"); return getContext().getSourcePageResolution(); } private void setMessage(String msg) { getContext().getMessages().add(new SimpleMessage(msg, new Object[0])); } } As you can see,
ProfileRepository-backed SecurityManagerThe implementation of the SecurityManager is pretty straightforward. It simply retrieves the current profile from the request (this uses the Here is the code : package net.sourceforge.jfacets.web.auth; import java.util.List; import javax.servlet.http.HttpServletRequest; import net.sourceforge.jfacets.IProfile; import net.sourceforge.jfacets.IProfileRepository; import net.sourceforge.jfacets.web.WebFacets; import net.sourceforge.jfacets.web.WebFacetsFilter; import net.sourceforge.stripes.action.ActionBeanContext; import net.sourceforge.stripes.security.controller.StripesSecurityManager; /** * Adapter for the stripes-security add-on, using the ProfileRepository and * ProfileLoaderFilter in order to check current profile against roles defined * on ActionBeans & their methods via <code>@Secure</code> annotations. */ public class ProfileBasedSecurityManager implements StripesSecurityManager { public boolean isUserInRole(List<String> roles, ActionBeanContext ctx) { HttpServletRequest request = ctx.getRequest(); // get hold of the current profile IProfile loggedProfile = ProfileLoaderFilter.getProfile(request); if (loggedProfile==null) { // shouldn't happen, but who knows ?? return false; } else { // get hold of the profile repository WebFacets wf = WebFacetsFilter.getJFacets(request); IProfileRepository profileRepository = wf.getProfileRepository(); // "roles" contains the allowed profile IDs, so we check in // the profile repository against each of these roles... boolean isInRole = false; for (String curPflId : roles) { IProfile curProfile = profileRepository.getProfileById(curPflId); if (profileRepository.isProfileEqualsOrDerivedFrom(loggedProfile, curProfile)) { isInRole = true; break; } } return isInRole; } } } Philosophical cornerACLs are handy, and achieves a pretty good security level for our webapp. Nevertheless, facets are a perfect candidate to encapsulate the interactions between the end-users (profiles) and the model objects in profiled commands. This way, you ensure that some actions can/cannot be performed for some user profiles, but it's not bound to any environment (your commands can be re-used as is in e.g. a Swing app !). |