web.xml security constraint combination of roles

11,209

This is not possible using declarative security (i.e. via web.xml). You can only list roles that have access to a resource like in the following:

<security-constraint>
<web-resource-collection>
    <web-resource-name>auth</web-resource-name>
    <url-pattern>/doc/profesionalCustomer.pdf</url-pattern>
</web-resource-collection>
<auth-constraint>
    <role-name>professional</role-name>
    <role-name>customer</role-name>
</auth-constraint>

however in this case you would grant access to all users that have either professional or customer role which is not what you want. There is no construct that allows you to grant access for a user that has a combination of roles.

One way you can go about it is to deal with it programmatically: direct a client to a servlet that examines whether the user is in both customer and professional role using HttpServletRequest#isUserInRole(String) and if it is forwards the request to the default servlet which retrieves the pdf. Furthermore if you want to defer what combination of roles are granted access to deployment time, rather then hard-coding it in the servlet you can have the granting servlet parameterized appropriately through /web-app/servlet/init-param or /web-app/context-param element of your web.xml.

The following is web.xml excerpt that would support this:

<servlet>
    <servlet-name>PDF Retriever</servlet-name>
    <servlet-class>com.stackoverflow.PDFRetrieverServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>PDF Retriever</servlet-name>
    <url-pattern>/docs/pdf/*</url-pattern>
</servlet-mapping>
<security-constraint>
    <web-resource-collection>
        <web-resource-name>PDF Docs - customer and professional only</web-resource-name>
        <url-pattern>/docs/pdf/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>*</role-name>
    </auth-constraint>
</security-constraint>
<security-constraint>
    <web-resource-collection>
        <web-resource-name>PDF Docs Private</web-resource-name>
        <url-pattern>/private/pdf/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name />
    </auth-constraint>
</security-constraint>`

and here is coding for doGet of the servlet:

protected void doGet(HttpServletRequest request, 
    HttpServletResponse response) throws ServletException, IOException {
    if (request.isUserInRole("customer") && request.isUserInRole("professional")) {
         String urlSuffix = request.getPathInfo();
         RequestDispatcher rd = request.getRequestDispatcher("/private/pdf"
              + urlSuffix);
          rd.forward(request, response);
     } else {
          response.sendError(HttpServletResponse.SC_FORBIDDEN);
     }
}
Share:
11,209
Pierpaolo
Author by

Pierpaolo

Updated on June 05, 2022

Comments

  • Pierpaolo
    Pierpaolo almost 2 years

    Given that I cannot create any new role because they are created in a CAS server and I do not have any control over them, is there a way to protect a PDF file to be opened only if a user has both "customer" and "professional" roles?

    In other words, considering the following three users:

    user1 has only "customer" role user2 has "customer" and "professional" roles user3 has "customer" and "professional" roles user4 has only "professional" role

    only user2 and user3 should be allowed to see the PDF.

    Basically, I would like to do something like:

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>auth</web-resource-name>
            <url-pattern>/doc/profesionalCustomer.pdf</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>professional,customer</role-name>
        </auth-constraint>
    </security-constraint>
    

    Is this even possible?

    Thanks in advance

  • Pierpaolo
    Pierpaolo about 11 years
    Thank you for the answer. My only concern is that if somebody knows the full path of the PDF file, he can access it directly without any control.
  • Nenad
    Nenad about 11 years
    @Pierpaolo I edited the answer to include web.xml and servlet code. To prevent everybody from accessing the PDF you place the URL with its actual location in a protected area that no role can access (your pdf files would be physically located under /private/pdf directory) - note the empty role-name element in the second security-constraint. The only access to it is through the PDFRetrievalServlet.