Skip to main content

Glassfish - Role Based Access Control (Part 1)

Posted by tchangu on June 11, 2006 at 9:55 PM PDT

Recently I have been exploring the various security features in Glassfish AS. In this blog entry, I hope to share some of my initial findings related to role based access control.



The following simple problem highlights the need for different roles. Lets say, user 'X' can perform transactions as well as view non-transactional parts of the application. However user 'A' can only view access the non-transactional parts of the application. For this simple case we have one servlet that is transactional that only few users (like X) could access while others (like A) are limited a general servlet. In order to accomplish this we go through a series of six simple steps and they are as follows:



STEP 1: The first step is to create two servlets. One is transactional in nature while the other is limited to general purpose view only type of access.



STEP 2: The next step is to define the role in the servlet. This can be accomplished using the DeclareRoles annotation type with role name as element.

@DeclareRoles("Transactional")
public class TransactionalServlet extends HttpServlet {
// doGet/doPost
}

@DeclareRoles("General")
public class GeneralServlet extends HttpServlet {
    // doGet/doPost
}

STEP 3: Next, specify in web.xml, declaratively aspects related to security.
First define the authentication method.
    <!-- LOGIN CONFIGURATION-->
    <login-config>
        <auth-method>FORM</auth-method>
        <realm-name>SecureWebFileRealm</realm-name>
        <form-login-config>
            <form-login-page>/pages/logon.jsp</form-login-page>
            <form-error-page>/pages/logonError.jsp</form-error-page>
        </form-login-config>
    </login-config>

There are couple of points in the above snippet that needs to be explained. First - this particular case uses form based authentication. Second is the use of realm-name. This need to match up with the name of realm that is configured in Glassfish AS using Glassfish admin console. In this particular case, we are using a file realm named SecureWebFileRealm.
Realm.jpg



STEP 4: Next, in web.xml specify security constraint that defines the mechanism to protect the web content. This is accomplished by using the security-constraint element of web.xml
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>RoleBasedAccessControl</web-resource-name>
            <url-pattern>/trans/*</url-pattern>
            <http-method>GET</http-method>
            <http-method>PUT</http-method>
        </web-resource-collection>
        <auth-constraint>
            <role-name>Transactional</role-name>
        </auth-constraint>
    </security-constraint>

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>RoleBasedAccessControl</web-resource-name>
            <url-pattern>/gen/*</url-pattern>
            <http-method>GET</http-method>
            <http-method>PUT</http-method>
        </web-resource-collection>
        <auth-constraint>
            <role-name>General</role-name>
        </auth-constraint>
    </security-constraint>

Here the authorization constraint is specified such that the role Transactional can access URL pattern /trans/* and the role General can access URL pattern /gen/*. Technically we could have specified the role name as * for the URL pattern /gen/*, which would allow any role to access this URL pattern.



STEP 5: Next, the security role mapping needs to be specified in sun-web.xml.
While using Netbeans as IDE, there is an aspect that one need to be aware of. If the role name were specified in web.xml using the security-role element and appropriately linked using security-role-ref element then Netbeans is smart enough to figure out the security role mapping.
    <servlet>
        <servlet-name>Transact</servlet-name>
        <servlet-class>com.test.web.TransactionalServlet</servlet-class>
        <security-role-ref>
            <role-name>Transactional</role-name>
            <role-link>Transactional</role-link>
        </security-role-ref>
    </servlet>
....
     <security-role>
         <role-name>Transactional</role-name>
    </security-role>

Inorder to complete the mapping one needs to create the Master List of Groups by clicking the Add Group button on the following screen.
Groups.jpg



Of course, the Group name should be the ones that were used while creating users using the Glassfish Admin console.
GroupsCreate.jpg



Once this is done, the next step is to do Role Assignments!!!!
RoleMapping.jpg


After this assignment, The following XML entries are added to sun-web.xml
  <security-role-mapping>
    <role-name>Transactional</role-name>
    <group-name>TransGroup</group-name>
  </security-role-mapping>
  <security-role-mapping>
    <role-name>General</role-name>
    <group-name>General</group-name>
  </security-role-mapping>

However if one were to use Annotation like we had defined earlier, the sun-web.xml doesn't seem to reflect the Security Role Mapping. In fact, if one were to add the security role mapping explicitly by editing the file using a text editor, then one could run into the danger of overwriting the security-role-mapping.



STEP 6: Done!
Accessing the URL (http://localhost:8080/testing/trans/Transact) will prompt for login (redirected to login.jsp specified in web.xml)
Logon.jpg

Logging in as user test1 that belongs to groups - TransactGroup and General - results in Transactional page. However logging in as test2 that belongs only to the group - General - results in a HTTP 403 (Not Authorized) which is subsequently redirected to a NotAuthorized page (HTTP 403 is mapped to this page in web.xml)



Logging in as user - test1 which belongs to group - General, TransactGroup

TransactionalPage.jpg


Logging in as user - test2 which belongs to group - General

TransactionalPage2.jpg



Enjoy!

Related Topics >>

Comments

Hi, I am doing the similar application as yours. What I did ...

Hi,
I am doing the similar application as yours. What I did is to apply the role access control for doGet and doPost within an servlet.
But the problem is the annotation seems not work. I put @RolesAllowed to doGet, put @DenyAll to doPost. But no matter which group the users belong to, they can do both doGet and doPost.
I was following each step you described above, do you have any idea why the annotations can not work?

Thank you so much for help