Restricting access to certain operations or resources is a common cross cutting concern in applications effectively running business operations in the real world.
This howto deals with this subject in the context of enterprise applications running on a Java application server, precisely an instance of the WildFly 8.2.1 server.
How can it be done to have a user log in and rely on the Enterprise JavaBeans implementation of security restriction?
The question in detail
For everyone even only briefly familiar with the design of server based appications it is common that the user is to operate on a web based representation of actions that are generally available by the running software. The accessablity of certain user requests can easily be done determining the visibility of concrete action elements (any action triggering button, radiobutton etc.) based upon information gathered or derived from a login procedure. Since the actual login process is done facing the user with a web page to input authentification information, there is no problem holding this information and determining the accessibility of presentation elements upon this, as all relevant code is running in the presentation tier.
But what about bookmarks and the generally not trustworthy requests sent by a client, since requests can easily be tailored to circumvent server side navigation rules, form content etc.?
This can be done securing the underlying business layer in order to make user operations, i.e. method invocations, dependent on the security information linked to the request.
To achieve this, four steps have to performed:
- Have the user input login credentials
- Validate the passed information against a data store
- On success, propagate this security-related information to the business tier of the application
- Implement code to restrict accessibility of parts of the code to users with the proper access rights
The following XML and Java code snippets are cut out of the code of a running JavaEE application, specifically an EAR deployment containing separate archives for presentation, business, persistence, common, ear, and test modules. The outlined example is functional running on an instance of the WildFly application server (8.2.1).
JSF code to enable the user to input user name and password:
Excerpt of the standalone.xml configuration of the WildFly 8.2.1 instance:
We define a security domain and link this to a login module to be used for authentification. Any authentification request that is relevant on the server side will be done using this login module. The crucial point here, as we use a database store for user credentials, is to define the queries delivering authentification information based upon the datasource, which of course has to be defined, as well.
As our sample application only uses local EJB injection, further configuration details may have to be assessed to have injected remote bean instances run in the desired security context.
Security context propagation
The assignation of the security domain to EJBs is done in a deploymant descriptor, jboss-ejb3.xml in our case:
Explicit definition of the security context, i.e. providing the EJB context with user principal and credentials, can be done accessing the http servlet request instance responsible for the JSF functionality and invoking the context authentification via the login(name, password) method:
The http servlet request’s login call is handled by the application server, invoking the configured login module. A customized login module can be written implementing the LoginModule interfaces in the javax.security.auth.spi and .auth.callback packages if a standard select by column SQL statement does not yield the required data. For details regarding the SQL query syntax for obtaining result sets compatible with standard login module’s requirements please visit the application server documentation site.
Method access restriction
The task on the business layer is to separate functional business aspects from each other and code methods whose functionality is strictly bound to an access right, or role in the EJB terminology. A simple EJB annotation does all further work. In our example even the login method of the business layer EJB can be security constrained, so we have to assess the LOGIN role to each user in order to access this tier, an EJBAccessException thrown otherwise. So even the very first user, an initial administrator, can only access the system when someone set up the underlying database table correctly.
The EJB technology provides an efficient way to implement a security mechanism with class or method level access restriction. A crucial step is to forward the security context of the presentation layer to the business layer, which requires the application server and deployment configurations to match. Security context propagation can be triggered by explicit Java code.