Architecture & DesignSecure Your Web Apps Using the Servlet API

Secure Your Web Apps Using the Servlet API

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

Prior to Java Enterprise Edition (Java EE) 7, there were only a couple of ways to secure your servlets. These included HTTP Basic Authentication and oAuth. In either case, a callback mechanism was employed to prompt the user for his or her credentials. If the credentials—defined in the web.xml file—were accepted, the user would be “authenticated.” On the server, his or her access rights had to be matched against the access rights required to access the resource. A successful match would allow the user to proceed; otherwise, he or she would receive a 403 error.

The Servlet API 3.1 introduced several new annotation types for use in Servlet classes, including @ServletSecurity, which is used to define access control constraints to servlets. By using annotations, we now can enforce security constraints without having to declare them in the web.xml file. In today’s article, we’ll configure a Banking servlet to invoke HTTP Basic Authentication using annotations.

Creating the Project

One of the best (if not the best) IDEs for Web application development is Eclipse. Its many amazing features and versatility make it a favorite among developers everywhere. We’ll be using Eclipse Oxygen here today.

You’ll also need a Web server that supports servlets. We’ll be using Tomcat 9 in our project. It’s an open source implementation of the Java Servlet, JavaServer Pages, Java Expression Language, and Java WebSocket technologies.

When you’re ready:

  1. Launch Eclipse and create a new Dynamic Web project.

On the New Dynamic Web Project dialog:

  1. Enter a Project name of “AcmeBankingApp”.
  2. Select “Apache Tomcat v9.0” for the Target runtime. If the “Apache Tomcat v9.0” item is not there, follow the steps listed in the next section, “Adding the Tomcat Runtime.”
  3. Accept all of the defaults. The dialog should like this:

    The Dynamic Web Project
    Figure 1: The Dynamic Web Project

  1. Click the Finish button to close the dialog and create the project.

Here’s our new project in the Project Explorer:

The new project
Figure 2: The new project

Adding the Tomcat Runtime

If you haven’t added your Tomcat server to the Eclipse Preferences page via Window -> Preferences -> Server Runtime Environments, you can add it from the Dynamic Web Project dialog by clicking the New Runtime…button.

On the New Server Runtime Environment dialog:

  1. Expand the Apache folder and select “Apache Tomcat v9.0” from the Runtime Environments list:

    New Server Runtime Environment
    Figure 3: New Server Runtime Environment

  2. Click Next >.
  3. On the next page, use the Browse…button to navigate to the installation directory of your Tomcat server:

    Tomcat Server
    Figure 4: Tomcat Server

  4. Accept all of the other defaults and click Finish to add the Tomcat server runtime and close the dialog.

You now will be able to select the “Apache Tomcat v9.0” item from the Target runtime list.

The Index File

The index.jsp page will be the landing page of our app. On it, we’ll place a button that invokes the account servlet’s deposit() method.

  1. Right-click the WebContent folder in the Project Explorer and select New -> JSP File from the popup menu.

On the New JSP file dialog:

  1. Name the file “index.jsp” and click Finishto create the file.

    The new JSP file
    Figure 5: The new JSP file

  2. In the Editor, paste the following code into the file:
    <%@ page language="java" contentType="text/html;
       charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
    <!DOCTYPE html>
    <html>
    <head>
       <meta http-equiv="Content-Type" content="text/html;
          charset=ISO-8859-1">
       <title>ACME Banking App</title>
    </head>
    <body>
       <h1>Welcome to the ACME Banking App!</h1>
       <p>What would you like to do today?</p>
       <form action="account" method="post">
          <button type="submit">Deposit $100.00</button>
       </form>
    </body>
    </html>
    
  3. Save the changes.

Clicking the Deposit button will send a POST request to the account servlet.

The Account Servlet

On the servlet, the doPost() method will handle the form request. To keep things simple, we’ll calculate the new account balance within the doPost() and return it to the browser—first, without any security:

  1. Right-click the project root in the Project Explorer and select New -> Servlet from the popup menu.

On the Create Servlet dialog:

  1. Provide a Java package name of “com.acmebanking.servlet” and a Class nameof “AccountServlet”:

    Creating the servlet
    Figure 6: Creating the servlet

  2. Click Finish to create the servlet.
  3. Add the following code to the AccountServlet.java file:
    package com.acmebanking.servlet;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @WebServlet(
       name = "BankAccountServlet",
       description = "Represents an ACME Bank Account and
          its transactions",
       urlPatterns = {"/account", "/bankAccount" })
    public class AccountServlet extends HttpServlet {
       private static final long serialVersionUID = 1L;
    
       private double accountBalance = 1000d;
    
       protected void doPost(HttpServletRequest request,
             HttpServletResponse response)
          throws ServletException, IOException {
             this.accountBalance = accountBalance + 100d;
    
             PrintWriter writer = response.getWriter();
             writer.println( "<html> Balance of the
                account is: $" 
                + this.accountBalance
                + "</html>");
             writer.flush();
       }
    }
    

Securing the Servlet

At this point, anyone can access the servlet via the “/account” or “/bankAccount” path.

Let’s protect it by using the @ServletSecurity annotation:

@ServletSecurity(
   value = @HttpConstraint(rolesAllowed = {"Member"}),
   httpMethodConstraints = {@HttpMethodConstraint(value = "POST",
      rolesAllowed = {"Admin"})})

In the preceding code, we’re assigning a general HTTP Constraint as well as one that applies specifically to the POST method. The rolesAllowed element accepts an array of zero or more role names. We haven’t defined any security roles yet, so when you build the project, the server will display a warning stating:

WARNING: Security role name [Admin] used in an <auth-constraint>
   without being defined in a <security-role>

Setting Role Names and Accounts

Tomcat maintains the list of user accounts in the tomcat-users.xml file. You can find it in this directory: CATALINA_HOME/conf (where the CATALINA_HOME environment variable is the Tomcat installation directory).

Make sure that you add the Admin user role and Jane user account:

<?xml version="1.0" encoding="UTF-8"?>
<tomcat-users>
   <role rolename="Admin"/>
   <user username="Jane" password="password" roles="Admin"/>
   <role rolename="manager-gui"/>
   <user username="tomcat" password="tomcat"
      roles="manager-gui"/>
</tomcat-users>

Running the App

Let’s take the app out for a test run now and see what happens.

  1. Right-click the project in the Project Explorer and select Run As -> Run on Server from the context menu.

On the Run on Server dialog:

  1. Make sure that your Tomcat server is selected and click Next >:

    Running on the server
    Figure 7: Running on the server

  2. On the next page, make sure that the AcmeBankingApp appears in the Configured list, and click Finishto launch the app:

    Ready to launch the app
    Figure 8: Ready to launch the app

  3. That will show the index.jsp page in the browser. Click the Deposit $100.00 buttonto invoke the servlet:

    Invoking the servlet
    Figure 9: Invoking the servlet

  4. Doing so will result in an “HTTP Status 403 – Forbidden” error:

    Access is forbidden
    Figure 10: Access is forbidden

    Don’t panic; that is exactly the result that we’re looking for. This error happened because we have included annotations on the servlet to only allow users with the role of “Admin” to access the servlet via POST submission.

In the next installment, we’ll configure the “user” and “web” XML files to have the server present an authentication form to access the Banking Servlet.

For reference, this entire project is hosted on GitHub.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories