Search This Blog

Thursday, September 15, 2011

Roles and Permissions with Spring Security 3


With the objective of achieving a bigger granularity and generality in the access control to a web application we propose the use of roles and permissions associated to those roles. Thus, the access control to the functionalities will be done through the definition of permissions, and each role will have associated a series of permissions. The main advantage of this separation between roles and permissions is that the modification or creation of a role only will imply the association to this role to the corresponding permissions you wish grant to it.

If you use Spring Security 3.x to manage the security in your web application, you will have realize that this framework does not offer support for the concept of permissions, allowing only the definition of a series of roles, which can be associated to users. Spring Security carries out the access control checking if a concrete role has been asigned to a user. But it allows to define groups of roles. We will take advantage of this feature to implement the concept of permissions:
  • Users will change their associated roles for a group of roles. That group of roles will represent the concept of roles. e.g. ROLE_ADMIN, ROLE_CLIENT, etc.
  • A group of roles will be composed of a set of roles, which we will use to define the permissions. e.g. PR_CLIENT_REGISTER, PR_CLIENT_MODIFY, PR_STUFF_CREATE, etc.
For each feature we want to control its access, we will check if the user has the corresponding permission associated to any of its roles. 

@AuthorizeInstantiation(UserRolesAuthorizer.PR_EVENT_CREATE)
public class AddEvent extends BasePage {
...
}

Through the activation of the Spring Security annotations in the configuration:

<global-method-security secured-annotations="enabled" />

we can establish conditions at component level:

@PreAuthorize("hasRole('PR_EVENT_READ')")
public List getEvents() { ... } 

We also keep the traditional Spring Security roles (ROLE_ADMIN, ROLE_CLIENT, etc.) to define at this level the access control to certain elements.

To get all that, we defined a new user representation that extends the org.springframework.security.core.userdetails.UserDetails class and includes:
  • A list of the group of roles that has asociated the autenticated user account.
  • A list of all the permissions associated to all the roles that the user has.

References:


Thursday, September 1, 2011

Preparing OpenLayers for the production environment

Inside the OpenLayers directory you can find the build subdiretory, in which there is a python script called build.py that allows us to create a custom OpenLayers.js file from a specified configuration.

OpenLayers ships with two default configuration files:
  • full.cfg: causes the build script to include everything.
  • lite.cfg: includes just a minimal amount of classes to create a WMS or tiled layer, not including controls.
We are going to create our custom configuration file from one of the previous ones in order to create a minimal javascript file for our application.

The first step is to find out which OpenLayers files we have to include for our application. One way to do that could be the following:

In order not to forget any of the OpenLayers classes, a good way to determine which classes to import could be to compare the importation of the all classes (checking the output of the build.py full.cfg execution) with all the ocurrences of the "OpenLayers." String in our javascript files (excluding of course the OpenLayers.js itself).
$ find . -name "*.js" -a \! -name OpenLayers.js | xargs sed -n 's/.*\(OpenLayers\.[A-Za-z0-9\
.]*\).*/\1/p'  | sort | uniq

OpenLayers.Bounds
OpenLayers.Bounds.fromArray
OpenLayers.Class
OpenLayers.Control
OpenLayers.Control.DeleteFeature
OpenLayers.Control.DrawFeature
OpenLayers.Control.KeyboardDefaults
OpenLayers.Control.LoadingPanel
OpenLayers.Control.MapInfo
OpenLayers.Control.Measure
OpenLayers.Control.ModifyFeature
OpenLayers.Control.MousePosition
OpenLayers.Control.MousePosition.prototype.formatOutput
OpenLayers.Control.Navigation
OpenLayers.Control.NavigationHistory
OpenLayers.Control.OverviewMap
OpenLayers.Control.PanPanel
OpenLayers.Control.Permalink
...

Aflter determining which classes have to be excluded from our javascript deployment we create a new configuration file:

mybuild.cfg

[first]
OpenLayers/SingleFile.js
OpenLayers.js
OpenLayers/BaseTypes.js
OpenLayers/BaseTypes/Class.js
OpenLayers/Util.js
Rico/Corner.js

[last]

[include]

[exclude]
Firebug/firebug.js
Firebug/firebugx.js
Gears/gears_init.js

OpenLayers/Lang/ar.js
OpenLayers/Lang/be-tarask.js
...
OpenLayers-2.10/build$ ./build.py mybuild.cfg MyOpenLayers.js
Merging libraries.
Importing: OpenLayers.js
Importing: Rico/Color.js
Importing: Rico/Corner.js
Importing: OpenLayers/Filter.js
Importing: OpenLayers/StyleMap.js
Importing: OpenLayers/Rule.js
...
Exporting:  OpenLayers/Protocol/WFS/v1_0_0.js
Exporting:  OpenLayers/Protocol/WFS/v1_1_0.js

Total files merged: 181
Compressing using jsmin.
Adding license file.
Writing to MyOpenLayers.js.
Done.

Finally, remember to change in the JavaScript file the occurrences of its name if you have used other different from the default one ("OpenLayers.js"):


$ sed 's/"OpenLayers.js"/"MyOpenLayers.js"/' MyOpenLayers.js > MyOpenLayers.js

Now we can see the difference between the complete OpenLayers JavaScript file and the custom file:

$ ls -lh
608K MyOpenLayers.js
924K OpenLayers.js

We have reduced the file size almost a 35% from the original. And in your case the difference could be even bigger (the javascript file obtained from the lite.cfg configuration has only 127KB).

Referencias: