Application managed security can be implemented using Controller hierarchies and lifecycle features.
All aspects of web application security
of course also pertain to Civilian applications, as do established security techniques and solutions.
In addition we present techniques how to implement application managed security based on features of the Controller class.
Container and application managed security
Authentication and access control are two main aspects of application security.
In the context of web applications they translate into questions such as
Container managed security
- how to authenticate clients which make a request?
- how to present a login form?
- how to implement session management?
- how to restrict access to resources?
- how to create responses tailored to access rights?
is a solution to enforce authentication and access control
at the container level whereas the application does not need to take care of these tasks.
In a servlet environment this is done using declarative definitions, e.g. in the web.xml.
But more complex applications often require application managed security –
security measures are implemented and enforced by the application.
Here are two use cases which cannot be addressed by declarative definitions in a servlet container:
- Access to a resource is always granted but the returned representation depends
on access rights of the user who is making the request.
E.g. in a returned HTML page specific menu items are only included for specific user roles,
page parts are different, etc.
- A resource displays data which is identified by a request parameter. Access control restricts an
user to certain partitions of the whole data space. Therefore requests are either
processed or rejected based on the request parameter. For instance (for a path parameter encoding a customer id)
a user may access the resource
/customers/1345 but not
Libraries like Spring Security or Apache Shiro can help you to implement application managed
security. In the following we discuss additional possibilities to implement authentication
and access control in your application using Controller features.
Use controller architecture for security
Requests to dynamic resources are processed by Controllers
The interplay of controller inheritance
allows for elegant solutions how to implement and enforce authentication and access control
within your application.
The CRM sample is used to exemplify the discussion.
Controller classes are derived from Controller
, but you can also
introduce base controller classes derived from Controller specific to your application.
Why would you want to do this? Of course to inherit functionality from base classes.
Now to an important observation: If the resource URLs exposed by your application form a well designed
URL tree it will most likely align well with a controller hierarchy:
||maps to resource
+- abstract SecuredController
+- abstract users.UsersController
+- abstract users.id.UserController
+- as inheritance relation and omitting the package prefix
We will use this feature to inherit security related functionality.
Controllers have a defined lifecycle and invocation
A controller instance is created to process a single request. Controllers define action
methods (for different RESTful scenarios) which are the entry points for processing.
Before and after a controller action method is invoked, initialization and cleanup methods
defined by the Controller
base class are called.
Our strategy to implement authentication and access control is based on the initialization method
Controller.checkAccess() which is called before the negotiated Controller action method.
checkAccess() commits the response, e.g. by sending a redirect or an error, the controller
action method is not invoked.
Prevent unauthenticated access using Controller.checkAccess()
of the CRM sample
is the common base class for all
controllers whose resource is behind the login wall.
- tests if the request is made by an authenticated user (testing the existence of a session attribute).
- If not, it sends a 401 unauthorized error (for ajax requests) or a redirect to the
/login resource (for non-ajax requests).
- If yes, it initializes a SessionUser property which is available to all derived classes.
is declared final, therefore it is guaranteed that no resource
behind the login wall can be accessed without proper authentication.
Implement and enforce any access control using Controller.checkAccess()
Naturally this technique can be used to implement any access control. As a second example the CRM sample allows
access to resources
only to users with the administrator role.
Again a common Controller base class org.civilian.samples.crm.web.root.users.UsersController
for these resources exists.
It inherits from
– that already guarantees only authenticated
access to resources
is declared final (to have a strong guarantee). To allow for additional
access control checks,
declares the method
which is called
when the request is properly authenticated.
uses this method to implement its check for the admin role.
If derived classes would require another
more specific access check, we could apply the technique again and provide for instance a method