Chapter 19

Security

Security is a very important aspect in web application development and deployment. This is especially true because web applications are accessible to anyone with a browser and Internet access. Securing an application can be done declaratively or programmatically. The following four issues are the cornerstones of web security: authentication, authorization, confidentiality and data integrity.

Authentication is to do with verifying the identity of a web entity, especially a user trying to access an application. You normally authenticate a user by asking the user for a user name and password.

Authorization is normally done after authentication is successful and is concerned with the access level an authenticated user has. It attempts to answer the question “Should an authenticated user be allowed to enter a certain area of the application?”

Confidentiality is an important topic because sensitive data, such as as credit card details or social security numbers, should be protected. And, as you may know, data is relayed from one computer to another before reaching its destination on the Internet. Intercepting it is not technically difficult. As such, sensitive data should be encrypted when being transferred over the Internet.

Since data packets can be easily intercepted, tampering with them is almost as easy to those equipped with the right tools and knowledge. Fortunately, it is also possible to maintain data integrity by making sure sensitive data travel through a secure channel.

You’ll learn about these aspects of security in this chapter. A lengthy discussion is also allocated for Transport Layer Security ( TLS), which is used as the protocol for creating secure channels over the Internet.

Note

Before TLS, Secure Sockets Layer (SSL) was commonly used to secure Internet communication. SSL is practically dead after Google publicly announced a vulnerability on SSL 3.0 on October 14, 2014. The Google security engineers who discovered this vulnerability called their finding POODLE (Padding Oracle On Downgraded Legacy Encryption). It is a man-in-the-middle exploit which takes advantage of Internet and security software clients’ fallback to SSL 3.0.

Authentication and Authorization

Authentication is the process of examining that someone is really who he/she claims to be. In a servlet/JSP application, authentication is normally done by asking the user for a user name and password.

Authorization is concerned with determining what level of access a user has. It applies to applications that consists of multiple zones where a user may have access to one section of an application but not to the others. For example, an online store may be divided into the general sections (for the general public to browse and search for products), the buyers section (for registered users to place orders), and the admin section (for administrators). Of the three, the admin section requires the highest level of access. Not only would admin users be required to authenticate themselves, they would also need to have been assigned access to the admin section.

Access levels are often called roles. At deployment a servlet/JSP application can be conveniently split into sections and configured so that each section can be accessed by users in a particular role. This is done by declaring security constraints in the deployment descriptor. In other words, declarative security. At the other end of spectrum, content restriction is also commonly achieved programmatically by trying to match pairs of user names and passwords with values stored in a database.

In the majority of servlet/JSP applications authentication and authorization are done programmatically by first authenticating the user name and password against a database table. Once authentication is successful, authorization can be done by checking another table or a field in the same table that stores user names and passwords. Using declarative security saves you some programming because the servlet/JSP container takes care of the authentication and authorization processes. In addition, the servlet/JSP container can be configured to authenticate against a database you’re already using in the application. On top of that, with declarative authentication the user name and password can be encrypted by the browser prior to sending them to the server. The drawback of declarative security is that the authentication method that supports data encryption can only be used with a default login dialog whose look and feel cannot be customized. This reason alone is enough to make people walk away from declarative security. The only method of declarative security that allows a custom HTML form to be used unfortunately does not encrypt the data transmitted.

Some parts of a web application, such as the Admin module, are not customer facing, so the look of the login form is of little relevance. In this case, declarative security can still be used.

The interesting part of declarative security is of course the fact that security constraints are not programmed into servlets. Instead, they are declared in the deployment descriptor at the time the application is deployed. As such, it allows considerable flexibility in determining the users and roles that will have access to the application or sections of it.

To use declarative security, you start by defining users and roles. Depending on the container you’re using, you can store user and role information in a file or database tables. Then, you impose constraints on a resource or a collection or resources in your application.

Now, how do you authenticate a user without programming? As you will find out later the answer lies in the HTTP and not in the Servlet specification.

Specifying Users and Roles

Every compliant servlet/JSP container must provide a way of defining users and roles. If you’re using Tomcat you can create users and roles by editing the tomcat-users.xml file in the conf directory. An example tomcat-users.xml file is given in Listing 19.1.

Listing 19.1: The tomcat-users.xml file

<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
    <role rolename="manager"/>
    <role rolename="member"/>
    <user username="tom" password="secret" roles="manager,member"/>
    <user username="jerry" password="secret" roles="member"/>
</tomcat-users>

The tomcat-users.xml file is an XML document having the tomcat-users root element. Within it are role and user elements. The role element defines a role and the user element defines a user. The role element has a rolename attribute that specifies the name of the role. The user element has username, password, and roles attributes. The username attribute specifies the user name, the password attribute the password, and the roles attribute the role or roles the user belongs to.

The tomcat-users.xml file in Listing 19.1 declares two roles (manager and member) and two users (tom and jerry). User tom is a member of both the member and manager roles whereas jerry only belongs to the member role. It is obvious that tom has more access to the application than jerry.

Tomcat also supports matching roles and users against database tables. You can configure Tomcat to use JDBC to authenticate users.

Imposing Security Constraints

You have learned that you can hide static resources and JSP pages by storing them under WEB-INF or a directory under it. A resource placed here cannot be accessed directly by typing its URL, but can still be a forward target from a servlet or JSP page. While this approach is simple and straightforward, the drawback is resources hidden here are hidden forever. There’s no way they can be accessed directly. If you simply want to protect resources from unauthorized users, you can put them in a directory under the application directory and declare a security constraint in the deployment descriptor.

The security-constraint element specifies a resource collection and the role or roles that can access the resources. This element can have two subelements, web-resource-collection and auth-constraint.

The web-resource-collection element specifies a collection of resources and can have any of these subelements: web-resource-name, description, url-pattern, http-method, and http-method-ommission.

The web-resource-collection element can have multiple url-pattern subelements, each of which refers to a URL pattern to which the containing security constraint applies. You can use an asterisk in the url-pattern element to refer to either a specific resource type (such as *.jsp) or all resources in a directory (such as /* or /jsp/*). However, you cannot combine both, i.e. refer to a specific type in a specific directory. Therefore, the following URL pattern meant to refer to all JSP pages in the jsp directory is invalid: /jsp/*.jsp. Instead, use /jsp/*, but this will also restrict any non-JSP pages in the jsp directory.

The http-method element names an HTTP method to which the enclosing security constraint applies. For example, a web-resource-collection element with a GET http-method element indicates that the web-resource-collection element applies only to the HTTP Get method. The security constraint that contains the resource collection does not protect against other HTTP methods such as Post and Put. The absence of the http-method element indicates the security constraint restricts access against all HTTP methods. You can have multiple http-method elements in the same web-resource-collection element.

The http-method-omission element specifies an HTTP method that is not included in the encompassing security constraint. Therefore, specifying <http-method-omission>GET</http-method-omission> restricts access to all HTTP methods except Get.

The http-method element and the http-method-omission element cannot appear in the same web-resource-collection element.

You can have multiple security-constraint elements in the deployment descriptor. If the auth-constraint element is missing from a security-constraint element, the resource collection is not protected. In addition, if you specify a role that is not defined by the container, no one will be able to access the resource collection directly. However, you can still forward to a resource in the collection from a servlet or JSP page.

As an example, the security-constraint elements in the web.xml file in Listing 19.2 restricts access to all JSP pages in the securitydemo1 application accompanying this book. As the auth-constraint element does not contain a role-name element, the resources are not accessible by their URLs.

Listing 19.2: Preventing access to resources in certain directories

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
    <!-- restricts access to JSP pages -->
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>JSP pages</web-resource-name>
            <url-pattern>*.jsp</url-pattern>
        </web-resource-collection>
        <!-- must have auth-constraint, otherwise the
            specified web resources will not be restricted -->
        <auth-constraint/>
    </security-constraint>
</web-app>

Now test it by directing your browser to this URL:

http://localhost:8080/securitydemo1/jsp/1.jsp

The servlet container will gently tell you off by sending an HTTP 403 error: Access to the requested resource has been denied.

Now let’s see how you can authenticate and authorize the user.

Authentication Methods

Now that you know how to impose security constraints on a resource collection, you should also learn how to authenticate users to access the resources. For resources that are secured declaratively, by using the security-constraint element in the deployment descriptor, authentication can be done by using the solutions that HTTP 1.1 offers: basic access authentication and digest access authentication. In addition, form-based access authentication can also be used.HTTP authentication is defined in RFC 2617. You can download the specification here:

http://www.ietf.org/rfc/rfc2617.txt

Basic Access Authentication

Basic access authentication, or simply Basic authentication, is an HTTP authentication for accepting a user name and password. In Basic access authentication a user who accesses a protected resource will be rejected by the server, which will return a 401 (Unauthorized) response. The response includes a WWW-Authenticate header containing at least one challenge applicable to the requested resource. Here is an example of such response:

HTTP/1.1 401 Authorization Required
Server: Apache-Coyote/1.1
Date: Wed, 30 Sep 2015 11:32:09 GMT
WWW-Authenticate: Basic realm="Members Only"

The browser would then display a Login dialog for the user to enter a user name and a password. When the user clicks the Login button, the user name will be appended with a colon and concatenated with the password. The string will then be encoded with the Base64 algorithm before being sent to the server. Upon a successful login, the server will send the requested resource.

Base64 is a very weak algorithm and as such it is very easy to decrypt Base64 messages. Consider using Digest access authentication instead.

The securitydemo2 application shows how to use the Basic access authentication. Listing 19.3 presents the deployment descriptor of the application. The first security-constraint element protects the JSP pages from direct access. The second one restricts access to the Servlet1 servlet to those in manager and member roles. The Servlet1 class is a simple servlet that forwards to 1.jsp and is presented in Listing 19.4.

Listing 19.3: The deployment descriptor of securitydemo2

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
    <!-- restricts access to JSP pages -->
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>JSP pages</web-resource-name>
            <url-pattern>*.jsp</url-pattern>
        </web-resource-collection>
        <!-- must have auth-constraint, otherwise the
            specified web resources will not be restricted -->
        <auth-constraint/>
    </security-constraint>
    
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Servlet1</web-resource-name>
            <url-pattern>/servlet1</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>member</role-name>
            <role-name>manager</role-name>
        </auth-constraint>
    </security-constraint>

    <login-config>
        <auth-method>BASIC</auth-method>
        <realm-name>Members Only</realm-name>
    </login-config>
</web-app>

The most important element in the deployment descriptor in Listing 19.3 is the login-config element. It has two subelements, auth-method and realm-name. To use the Basic access authentication, you must give it the value BASIC (all capitals). The realm-name element should be given a name to be displayed in the browser Login dialog.

Listing 19.4: The Servlet1 class

package servlet;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
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(urlPatterns = { "/servlet1" })
public class Servlet1 extends HttpServlet {

    private static final long serialVersionUID = -15560L;

    public void doGet(HttpServletRequest request,
            HttpServletResponse response) throws ServletException,
            IOException {
        RequestDispatcher dispatcher = 
                request.getRequestDispatcher("/jsp/1.jsp");
        dispatcher.forward(request,  response);
    }
}

To test the Basic access authentication in securitydemo2, try accessing the restricted resource in it using this URL.

http://localhost:8080/securitydemo2/servlet1

Instead of seeing the output of Servlet1, you’ll be prompted for a username and password like the screen shot in Figure 19.1.

Figure 19.1: Basic authentication

Since the auth-constraint element mapped to Servlet1 specifies both manager and member roles, you can use either tom or jerry to login.

Digest Access Authentication

Digest access authentication, or Digest authentication for short, is also an HTTP authentication and is similar to Basic access authentication. Instead of using the weak Base64 encryption algorithm, Digest access authentication uses the MD5 algorithm to create a hash of the combination of the user name, realm name, and the password and sends the hash to the server. Digest access authentication is meant to replace Basic access authentication as it offer a more secure environment.

Configuring an application to use Digest access authentication is similar to using Basic access authentication. In fact, the only difference is the value of the auth-method element within the login-config element. For Digest access authentication, its value must be DIGEST (all uppercase).

As an example, the securitydemo3 application demonstrates the use of Digest access authentication. The deployment descriptor for this application is given in Listing 19.5.

Listing 19.5: The deployment descriptor for Digest authentication

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
    <!-- restricts access to JSP pages -->
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>JSP pages</web-resource-name>
            <url-pattern>*.jsp</url-pattern>
        </web-resource-collection>
        <!-- must have auth-constraint, otherwise the
            specified web resources will not be restricted -->
        <auth-constraint/>
    </security-constraint>

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Servlet1</web-resource-name>
            <url-pattern>/servlet1</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>member</role-name>
            <role-name>manager</role-name>
        </auth-constraint>
    </security-constraint>
    
    <login-config>
        <auth-method>DIGEST</auth-method>
        <realm-name>Digest authentication</realm-name>
    </login-config>
</web-app>

To test the application, direct your browser to this URL:

http://localhost:8080/securitydemo3/servlet1

Figure 19.2 shows the Login dialog for Digest access authentication.

Figure 19.2: Digest authentication

Form-based Authentication

Basic and Digest access authentications do not allow you to use a customized login form. If you must have a custom form, then you can use form-based authentication. As the values transmitted are not encrypted, you should use this in conjunction with SSL.

With form-based authentication, you need to create a Login page and an Error page, which can be HTML or JSP pages. The first time a protected resource is requested, the servlet/JSP container will send the Login page. Upon a successful login, the requested resource will be sent. If login failed, however, the user will see the Error page.

To use form-based authentication, the auth-method element in your deployment descriptor must be given the value FORM (all upper case). In addition, the login-config element must have a form-login-config element with two subelements, form-login-page and form-error-page. Here is an example of the login-config element for form-based authentication.

    <login-config>
        <auth-method>FORM</auth-method>
        <form-login-config>
            <form-login-page>/login.html</form-login-page>
            <form-error-page>/error.html</form-error-page>
        </form-login-config>
    </login-config>

Listing 19.6 shows the deployment descriptor of securitydemo4, an example that utilizes form-based authentication.

Listing 19.6: The deployment descriptor for form-based authentication

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
    <!-- restricts access to JSP pages -->
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>JSP pages</web-resource-name>
            <url-pattern>*.jsp</url-pattern>
        </web-resource-collection>
        <!-- must have auth-constraint, otherwise the
            specified web resources will not be restricted -->
        <auth-constraint/>
    </security-constraint>

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Servlet1</web-resource-name>
            <url-pattern>/servlet1</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>member</role-name>
            <role-name>manager</role-name>
        </auth-constraint>
    </security-constraint>
    
    <login-config>
        <auth-method>FORM</auth-method>
        <form-login-config>
            <form-login-page>/login.html</form-login-page>
            <form-error-page>/error.html</form-error-page>
        </form-login-config>
    </login-config>
</web-app>

The form-login-page element refers to the login.html page in Listing 19.7 and the form-error-page element references the error.html page in Listing 19.8.

Listing 19.7: The login.html page

<!DOCTYPE HTML>
<html>
<head>
    <title>Login</title>
</head>
<body>
<h1>Login Form</h1>
<form action='j_security_check' method='post'>
<p>
    <label>User Name: <input name='j_username'/></label>
</p>
<p>
    <label>Password: <input type='password' name='j_password'/></label>
</p>
<p>
    <label><input type='submit' value='Login'/></label>
</p>
</form>
</body>
</html>

Listing 19.8: The error.html page

<!DOCTYPE HTML>
<html>
<head>
<title>Login error</title>
</head>
<body>
Login failed.
</body>
</html>

To test the form-based authentication in securitydemo4, direct your browser to this URL.

http://localhost:8080/securitydemo4/servlet1

Figure 19.3 shows the login.html for the user to login.

Figure 19.3: Form-based authentication

Client Certificate Authentication

Also called the client-cert authentication, the client certificate authentication works over HTTPS (HTTP over SSL or HTTP over TLS since SSL is dead) and requires that every client have a client certificate. This is a very strong authentication mechanism but is not suitable for applications deployed over the Internet as it is impractical to demand that every user own a digital certificate. However, this authentication method can be used to access intranet applications within an organization.

SSL and TLS

Originally developed by Netscape, the SSL protocol (and now TLS) enables secure communications over the Internet and at the same time ensures the confidentiality and data integrity.

To fully understand how TLS and SSL work, there are a number of technologies that you need to learn, from cryptography to private and public key pairs to certificates. This section discusses TLS and SSL and its components in detail.

Cryptography

From time to time there has always been a need for secure communication channels, i.e. where messages are safe and other parties cannot understand and tamper with the messages even if they can get access to them.

Historically, cryptography was only concerned with encryption and decryption, where two parties exchanging messages can be rest assured that only they can read the messages. In the beginning, people encrypted and decrypted messages using symmetric cryptography. In symmetric cryptography, you use the same key to encrypt and decrypt messages. Here is a very simple encryption/decryption technique.

Suppose, the encryption method uses a secret number to shift forward each character in the alphabet. Therefore, if the secret number is 2, the encrypted version of "ThisFriday" is "VjkuHtkfca". When you reach the end of the alphabet, you start from the beginning, therefore y becomes a. The receiver, knowing the key is 2, can easily decrypt the message.

However, symmetric cryptography requires that both parties know in advance the key for encryption/decryption. Symmetric cryptography is not suitable for the Internet for the following reasons

  • Two people exchanging messages often do not know each other. For example, when buying a book at Amazon.com you need to send your particulars and credit card details. If symmetric cryptography was to be used, you would have to call Amazon.com prior to the transaction to agree on a key.
  • Everyone wants to be able to communicate with many other parties. If symmetric cryptography was used, everyone would have to maintain different unique keys, each for a different party.
  • Since you do not know the entity you are going to communicate with, you need to be sure that they are really who they claim to be.
  • Messages over the Internet pass through many different computers. It is fairly trivial to tap other people’s messages. Symmetric cryptography does not guarantee that a third party may not tamper with the data.

Therefore, today secure communication over the Internet uses asymmetric cryptography that offers these three features:

  • encryption/decryption. Messages are encrypted to hide the messages from third parties. Only the intended receiver can decrypt them.
  • authentication. Authentication verifies that an entity is who it claims to be.
  • data integrity. Messages sent over the Internet pass many computers. It must be ensured that the data sent is unchanged and intact.

In asymmetric cryptography, public key encryption is used. With this type of encryption, data encryption and decryption is achieved through the use of a pair of asymmetric keys: a public key and a private key. A private key is private. The owner must keep it in a secure place and it must not fall into the possession of any other party. A public key is to be distributed to the public, usually downloadable by anyone who would like to communicate with the owner of the keys. You can use tools to generate pairs of public keys and private keys. These tools will be discussed later in this chapter.

The beauty of public key encryption is this: data encrypted using a public key can only be decrypted using the corresponding private key; at the same token data encrypted using a private key can only be decrypted using the corresponding public key. This elegant algorithm is based on very large prime numbers and was invented by Ron Rivest, Adi Shamir, and Len Adleman at Massachusetts Institute of Technology (MIT) in 1977. They simply called the algorithm RSA, based on the initials of their last names.

The RSA algorithm proves to be practical for use on the Internet, especially for e-commerce, because only the vendor is required to have a key pair for secure communications with all its buyers.

An illustration of how public key encryption works normally use two figures called Bob and Alice, so I’ll use them too here.

Encryption/Decryption

One of the two parties who want to exchange messages must have a pair of keys. Suppose Alice wants to communicate with Bob and Bob has a public key and a private key. Bob will send Alice his public key and Alice can use it to encrypt messages sent to Bob. Only Bob can decrypt them because he owns the corresponding private key. To send a message to Alice, Bob encrypts it using his private key and Alice can decrypt it using Bob’s public key.

However, unless Bob can meet with Alice in person to hand over his public key, this method is far from perfect. Anybody with a pair of keys can claim to be Bob and there is no way Alice can find out. On the Internet, where two parties exchanging messages often live half a globe away, meeting in person is often not possible.

Authentication

In TLS and SSL, authentication is addressed by introducing certificates. A certificate contains the following:

  • a public key
  • information about the subject, i.e. the owner of the public key.
  • the certificate issuer’s name.
  • some timestamp to make the certificate expire after a certain period of time.

The crucial thing about a certificate is that it must be digitally signed by a trusted certificate issuer, such as VeriSign or Thawte. To digitally sign an electronic file (a document, a jar file, etc) is to add your signature to your document/file. The original file is not encrypted, and the real purpose of signing is to guarantee that the document/file has not been tampered with. Signing a document involves creating a digest of the document and encrypting the digest using the signer’s private key. To check if the document is still in its still original condition, you perform these two steps.

1. Decrypt the digest accompanying the document using the signer’s public key. You will soon learn that the public key of a trusted certificate issuer is widely available.

2. Create a digest of the document.

3. Compare the result of Step 1 and the result of Step 2. If the two match, then the file has not been tampered with.

Such authentication method works because only the holder of the private key can encrypt the document digest, and this digest can only be decrypted using the corresponding public key. Assuming you trust that you hold the original public key, then you know that the file has not been changed.

Note

Because certificates can be digitally signed by a trusted certificate issuer, people make their certificates publicly available, instead of their public keys.

There are a number of certificate issuers, including VeriSign and Thawte. A certificate issuer has a pair of public key and private key. To apply for a certificate, Bob has to generate a pair of keys and send his public key to a certificate issuer, who would later authenticate Bob by asking him to send a copy of his passport or other types of identification. Having verified Bob, a certificate issuer will sign the certificate using its private key. By ‘signing’ it means encrypting. Therefore, the certificate can only be read by using the certificate issuer’s public key. The public key of a certificate issuer is normally distributed widely. For example, Internet Explorer, Netscape, FireFox and other browsers by default include several certificate issuers’ public keys.

For example, in IE, click Tools --> Internet Options --> Content --> Certificates --> Trusted Root Certification Authorities tab to see the list of certificates. (See Figure 19.4).

Figure 19.4: Certificate issuers whose public keys are embedded in Internet Explorer

Now, having a certificate, Bob will distribute the certificate instead of his public key before exchanging messages with another party.

Here is how it works.

A->B Hi Bob, I’d like to speak with you, but first I need to make sure that you’re really Bob.

B->A Fair enough, here is my certificate

A->B This is not sufficient, I need something else from you

B->A Alice, it’s really me + [message digest encrypted using Bob’s private key]

In the last message from Bob to Alice, the message has been signed using Bob’s private key, to convince Alice that the message is authentic. This is how authentication is proved. Alice contacts Bob and Bob sends his certificate. However, a certificate alone is not sufficient because anyone can get Bob’s certificate. Remember that Bob sends his certificate to anyone who wants to exchange messages with him. Therefore, Bob sends her a message (“Alice, it’s really me”) and the digest of the same message encrypted using his private key.

Alice gets Bob’s public key from the certificate. She can do it because the certificate is signed using the certificate issuer’s private key and Alice has access to the certificate issuer’s public key (her browser keeps a copy of it). Now, she also gets a message and the digest encrypted using Bob’s private key. All Alice needs to do is digest the message and compare it with the decrypted digest Bob sent. Alice can decrypt it because it has been encrypted using Bob’s private key, and Alice has a copy of Bob’s public key. If the two match, Alice can be sure that the other party is really Bob.

The first thing Alice does after authenticating Bob is to send a secret key that will be used in subsequent message exchange. That’s right, once a secure channel is established, SSL uses symmetric encryption because it is much faster than asymmetric encryption.

Now, there is still one thing missing from this picture. Messages over the Internet pass many computers. How do you make sure the integrity of those messages because anyone could intercept those messages on the way?

Data Integrity

Mallet, a malicious party, could be sitting between Alice and Bob, trying to decipher the messages being sent. Unfortunately for him, even though he could copy the messages, they are encrypted and Mallet does not know the key. However, Mallet could still destroy the messages or not relay some of them. To overcome this, SSL introduces a message authentication code (MAC). A MAC is a piece of data that is computed by using a secret key and some transmitted data. Because Mallet does not know the secret key, he cannot compute the right value for the digest. The message receiver can and therefore will discover if there is an attempt to tamper with the data, or if the data is not complete. If this happens, both parties can stop communicating.

One of such message digest algorithm is MD5. It is invented by RSA and is very secure. If 128-bit MAC values are employed, for example, the chance of a malicious party’s of guessing the right value is about 1 in 18,446,744,073,709,551,616, or practically never.

How TLS and SSL Work

Now you know how TLS and SSL address the issues of encryption/decryption, authentication, and data integration, let’s review how TLS and SSL work. This time, let’s take Amazon.com as an example (in lieu of Bob) and a buyer (instead of Alice). Amazon.com, like any other bona fide e-commerce vendor has applied for a certificate from a trusted certificate issuer. The buyer is using Internet Explorer, which embeds the public keys of trusted certificate issuers. The buyer does not really need to know about how TLS and SSL work and does not need to have a public key or a private key. One thing he needs to ensure is that when entering important details, such as a credit card number, the protocol being used is HTTPS, instead of HTTP. This has to appear on the URL box. Therefore, instead of http://www.amazon.com, it has to start with https. For instance: https://secure.amazon.com. Some browsers also display a secure icon in the Address box. Figure 19.5 shows a secure sign in IE.

Figure 19.5: The secure icon in IE

When the buyer enters a secure page (when he has finished shopping), this is the sequence of events that happens in the background, between his browser and Amazon’s server.

browser: Are you really Amazon.com?

server: Yes, here is my certificate.

The browser then checks the validity of the certificate using the certificate issuer’s public key to decrypt it. If something is wrong, such as if the certificate has expired, the browser warns the user. If the user agrees to continue despite the certificate being expired, the browser will continue.

browser: A certificate alone is not sufficient, please send something else.

server: I’m really Amazon.com + [the digest of the same message encrypted using Amazon.com’s private key].

The browser decrypts the digest using Amazon’s public key and create a digest of “I’m Really Amazon.com”. If the two match, authentication is successful. The browser will then generate a random key, encrypt it using Amazon’s public key. This random key is to encrypt and decrypt subsequent messages. In other words, once Amazon is authenticated, symmetric encryption is used because it is faster then asymmetric cryptography. In addition to messages, both parties also send message digests for making sure that the messages are intact and unchanged.

Appendix E, “TLS Certificates,” explains how you can create a digital certificate of your own and provides step-by-step instructions to generate a public/private key pair and have a trusted authority sign the public key as a certificate.

Programmatic Security

Even though declarative security is easy and straightforward, there are rare cases where you want to write code to secure your application. For this purpose, you can use the security annotation types and methods in the HttpServletRequest interface. Both are discussed in this section.

Security Annotation Types

In the previous section you learned how to restrict access to a collection of resources using the security-constraint element in the deployment descriptor. One aspect of this element is that you use a URL pattern that matches the URLs of the resources to be restricted. Servlet 3 comes with annotation types that can perform the same job on a servlet level. Using these annotation types, you can restrict access to a servlet without adding a security-constraint element in the deployment descriptor. However, you still need a login-config element in the deployment descriptor to choose an authentication method.

There are three annotation types in the javax.servlet.annotation package that are security related. They are ServletSecurity, HttpConstraint, and HttpMethodConstraint.

The ServletSecurity annotation type is used in a servlet class to impose security constraints on the servlet. A ServletSecurity annotation may have the value and httpMethodConstraints attributes.

The HttpConstraint annotation type defines a security constraint and can only be assigned to the value attribute of the ServletSecurity annotation. If the httpMethodConstraints attribute is not present in the enclosing ServletSecurity annotation, the security constraint imposed by the HttpConstraint annotation applies to all HTTP methods. Otherwise, the security constraint applies to the HTTP methods defined in the httpMethodConstraints attribute. For example, the following HttpConstraint annotation dictates that the annotated servlet can only be accessed by those in the manager role.

@ServletSecurity(value = @HttpConstraint(rolesAllowed = "manager"))

Of course, the annotations above can be rewritten as follows.

@ServletSecurity(@HttpConstraint(rolesAllowed = "manager"))

You still have to declare a login-config element in the deployment descriptor so that the container can authenticate the user.

Setting TransportGuarantee.CONFIDENTIAL to the transportGuarantee attribute of an HttpConstraint annotation will make the servlet only available through a confidential channel, such as SSL.

@ServletSecurity(@HttpConstraint(transportGuarantee =
TransportGuarantee.CONFIDENTIAL))

If the servlet/JSP container receives a request for such a servlet through HTTP, it will redirect the browser to the HTTPS version of the same URL.

The HttpMethodConstraint annotation type specifies an HTTP method to which a security constraint applies. It can only appear in the array assigned to the httpMethodConstraints attribute of a ServletSecurity annotation. For example, the following HttpMethodConstraint annotation restricts access to the annotated servlet via HTTP Get to the manager role. For other HTTP methods, no restriction exists.

@ServletSecurity(httpMethodConstraints = {
    @HttpMethodConstraint(value = "GET", rolesAllowed = "manager")
})

Note that if the rolesAllowed attribute is not present in an HttpMethodConstraint annotation, no restriction applies to the specified HTTP method. For example, the following ServletSecurity annotation employs both the value and httpMethodConstraints attributes. The HttpConstraint annotation defines roles that can access the annotated servlet and the HttpMethodConstraint annotation, which is written without the rolesAllowed attribute, overrides the constraint for the Get method. As such, the servlet can be accessed via Get by any user. On the other hand, access via all other HTTP methods can only be granted to users in the manager role.

@ServletSecurity(value = @HttpConstraint(rolesAllowed = "manager"),
    httpMethodConstraints = {@HttpMethodConstraint("GET")}
)

However, if the emptyRoleSemantic attribute of the HttpMethodConstraint annotation type is assigned EmptyRoleSemantic.DENY, then the method is restricted for all users. For example, the servlet annotated with the following ServletSecurity annotation prevents access via the Get method but allows access to all users in the member role via other HTTP methods.

@ServletSecurity(value = @HttpConstraint(rolesAllowed = "member"),
httpMethodConstraints = {@HttpMethodConstraint(value = "GET", 
    emptyRoleSemantic = EmptyRoleSemantic.DENY)}
) 

Servlet Security API

Besides the annotation types discussed in the previous section, programmatic security can also be achieved using the following methods in the HttpServletRequest interface.

java.lang.String getAuthType()

Returns the authentication scheme used to protect the servlet or null if no security constraint is being applied to the servlet.

java.lang.String getRemoteUser()

Returns the login of the user making this request or null if the user has not been authenticated.

boolean isUserInRole(java.lang.String role)

Returns a boolean indicating whether or not the user belongs to the specified role.

java.lang.Principal getUserPrincipal()

Returns a java.security.Principal containing the details of the current authenticated user or null if the user has not been authenticated.

boolean authenticate(HttpServletResponse response) throws java.io.IOException

Authenticates the user by instructing the browser to display a login form.

void login(java.lang.String userName, java.lang.String password) throws javax.servlet.ServletException

Attempts to log the user in using the supplied user name and password. The method does not return anything if login was successful. Otherwise, it will throw a ServletException.

void logout() throws javax.servlet.ServletException

Logs the user out.

As an example, the ProgrammaticServlet class in Listing 19.9 is part of the securitydemo5 sample application that shows how to authenticate the user programmatically. It is accompanied by the deployment descriptor in Listing 19.10 that declares a login-config element that employs Digest access authentication.

Listing 19.9: The ProgrammaticServlet class

package 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(urlPatterns = { "/prog" })
public class ProgrammaticServlet extends HttpServlet {

    private static final long serialVersionUID = 87620L;

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        if (request.authenticate(response)) {
            response.setContentType("text/html");
            PrintWriter out = response.getWriter();
            out.println("Welcome");
        } else {
            // user not authenticated
            // do something
            System.out.println("User not authenticated");
        }
    }
}

Listing 19.10: The deployment descriptor for securitydemo5

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
    <login-config>
        <auth-method>DIGEST</auth-method>
        <realm-name>Digest authentication</realm-name>
    </login-config>
</web-app>

When the user first requests the servlet, the user is not authenticated and the authenticate method returns false. As a result, the servlet/JSP container will send a WWW-Authenticate header, causing the browser to show a Login dialog for Digest access authentication. When the user submits the form with the correct user name and password, the authenticate method returns true and the Welcome message is shown.

You can test the application by using this URL:

http://localhost:8080/securitydemo5/prog

Summary

In this chapter you have learned how to achieve the four pillars of web security: authentication, authorization, confidentiality, and data integrity. Servlet technology allows you to secure your applications declaratively and programmatically.

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

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