Securing the web module

The first resource we want to protect is the web resource, a servlet, as follows:

package net.lucamasini.security;

@WebServlet(name="MyWorkServlet",
        urlPatterns={"/myprotectedresource"})
public class MyProtectedServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req,
                 HttpServletResponse resp) 
        throws ServletException, IOException {
        Principal userPrincipal = req.getUserPrincipal();
resp.getWriter().println(userPrincipal!=null?userPrincipal.getName(): "anonymous");
    }
}

Here we can see the power of Java EE 6: we don't need to write XML to declare a servlet and to bind it to a URL, a single annotation is enough. Now, after compiling and launching, the deploy goal will allow us to call http://localhost:7001/chapter3-web/myprotectedresource and see the string anonymous; this means our servlet has been deployed and the user is still anonymous.

Now we can go a step further and protect the web resource. Again, a simple annotation does the work without the need to edit web.xml, as follows:

@ServletSecurity(@HttpConstraint(rolesAllowed={"my-user"}))

If we call the URL now, entering WebLogic's administrator principals (weblogic/weblog1c when we created the domain with the create-domain goal) should obtain a 403 FORBIDDEN HTTP status code. This means that the user has been recognized, but has no rights to access the resource. This may sound a little strange: the Administrator group can do everything in our domain but it is perfectly valid that our application doesn't trust such users!

The problem is that we never specified to WebLogic that the my-user role is mapped to the Administrator's principal.

Now we have to decide what kind of role-mapping strategy we need to use. A typical Java EE mapping is done using custom deployment descriptors (like the weblogic.xml custom deployment descriptor), but this has the prerequisite of knowing about the groups and users that will use our application.

If, instead, we can't know in advance which are users and which are groups, we need to change those mappings without redeployment, or if the mapping is too complex to be defined using a one-to-many relationship (a role mapped to many principals), we have another chance in WebLogic using its runtime custom Roles Mapper.

Standard DD mapping

Let's start with the standard DD mapping. For this, finally, we need to write XML, the custom deployment descriptor weblogic.xml, into the src/main/webapp/WEB-INF folder, as follows:

<?xml version="1.0" encoding="UTF-8"?>
<weblogic-web-app xmlns="http://xmlns.oracle.com/weblogic/weblogic-web-app">
    <security-role-assignment>
        <role-name>my-user</role-name>
        <principal-name>users</principal-name>
    </security-role-assignment>
</weblogic-web-app>

Here, we are using one of the embedded groups in WebLogic; all users are implicitly also members of the users group, and this time calling the URL will work and we will see weblogic appear on our browser.

Custom Roles Mapping

Mapping of roles is done by WebLogic Server XACML Role Mapping Provider, which allows us to use the console or its runtime MBean, to declare roles under certain conditions. In fact, we can do everything that the standard DD does, such as declare a role if one or more groups are principals of the current subject, but also declare rules like is in development mode or in not into the group. For a complete list you can view the official documentation.

Now we start doing the same stuff done into the DD, that is, declaring that every principal that is in the users group has the role my-user. We could do this in a very fast and intuitive way using the Web Console, but in this chapter we will do everything using Maven and this is not an exception.

We must create the file create-roles.py under the chapter3-ear folder with the following content:

connect('weblogic','weblog1c')
xacml = cmo.getSecurityConfiguration().getDefaultRealm().lookupRoleMapper('XACMLRoleMapper')
xacml.createRole(None,'my-user',None)
xacml.setRoleExpression(None,'my-user', 'Grp(users)')

And then run the following WLST script with the Maven plugin:

mvn wls:wlst -DfileName=create-roles.py

By doing this, we create a global role called my-user that we can check under the console at Home | Summary of Security Realms | myrealm | Realm Roles | Global Roles.

Tip

Deployment roles

We are not limited to creating global roles; we can also create a role that is local to a specific deployed application

Of course, calling http://localhost:7001/chapter3-web/myprotectedresource will have the same desired effect of showing us the current logged in user.

Programmatic security

There are certain situations when we can't rely only on declarative security; when we need another level of intelligence to understand if the user can or cannot access the requested resource. In effect, the semantics of the standard declarative security is quite primitive—a list of principals in logical OR; not enough for many business case.

Imagine, for instance, that you need to check if a user is a member of at least two groups, if the time of the day is in a certain range, or if the user is contained in a business table.

In all these cases, we need to code the security of our application, and Java EE doesn't help much. On the web tier, we have only a single API call that can tell us if a user has or does not have a certain role. We can add the following line of code to our servlet to experiment:

resp.getWriter().
      println("my-user: "+req.isUserInRole("my-user"));

Now, calling our URL will also display my-user: true, because we are also using declarative security to allow access to that resource. Usually, we must disable declarative security when we need programmatic security and then code our business rule.

Programmatic security with WebLogic XACML provider

Under WebLogic, we have the chance to skip security coding when using Customer Roles. In fact, when we declare our roles we have a richer semantic, and if you need a user that is a member of two groups—users and Administrators—you can write the following:

Grp(users)&Grp(Administrators)

But this Provider is not limited to this. We can also do the following:

  • Negate conditions
  • Check if the server is in the development mode
  • Check if date and time follow some conditions, such as day-of-the-week and range-of-hours
  • Contextual elements, like the current HTTP request or the socket port

Using the XACML Role Mapping Provider in a correct way can spare us from coding programmatic security using a well-defined standard like OASIS's eXtensible Access Control Markup Language (XACML).

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset