Declarative SecurityS2C Home « Declarative Security

Securing our web applications is one of the most important parts of web development and considering that anyone with an internet connection and a browser can access them, we need to ensure our security is up to the task. We can secure our web applications declaratively via the DD without using any code or using a combination of declarative and programmatic security. In the first of two lessons on security we look at securing our web applications declaratively via the DD without having to change a single line of code.

Within web applications there are four topics which cover the various areas of web security these being: authentication, authorization, confidentiality and data integrity. We talk about each area of web security in the following sections in much more detail.

AuthenticationTop

Authentication is about providing a means whereby two communicating entities; which in terms of Java we can think of as client using a web browser to point to a resource on our server and the container verifying the said resource is available to this client. The communicating entities could also be resources communication with each other, but the above analogy will do for this lesson.

Authentication is generally achieved by sending the client a form where they have to fill in a username and password. The form can be declared declaratively, via the DD, which then uses HTTP protocol to create a form, which varies dependant upon the browser being used. This might not be acceptable for customer facing authentication but is fine for internal authentication. We can also create a custom form programmatically and we look at the DD entry for this below how we go about coding a custom form in the Programmatic Security lesson.

The container then validates entries in these two fields against a vendor specific user file, which for Tomcat would be the tomcat-users.xml file found within the conf directory, or from records held on a relational database or LDAP system.

The following code shows the contents of the tomcat-users.xml file after removing all the comments and uncommenting the file. We have rolenames followed by a username and password and the roles applicable to that user which can be multiple roles. The actual layout will differ between different server vendors but the idea is the same, we authenticate a user via their username and password and we authorize them using constraints within the DD, which we look at in the next section. You can think of a role in terms of the access a user has to a web application.


<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
  <role rolename="tomcat"/>
  <role rolename="role1"/>
  <user username="tomcat" password="tomcat" roles="tomcat"/>
  <user username="both" password="tomcat" roles="tomcat,role1"/>
  <user username="role1" password="tomcat" roles="role1"/>
</tomcat-users>


The above tomcat-users.xml file is perfect for our security lesson but not really suitable for a production environment as we would need to change this file every time we got a new user. Make sure you change and save the file as above or the examples later in the lesson won't work.

Authentication TypesTop

To implement authentication within our web applications we need to add entries to the DD for the type of authentication we require. The top-level <login-config> element is used to declare that authentication is required. Within the <login-config> element, we can enter an optional authentication method, the optional realm name that should be used for this application and the attributes that are needed by the form login mechanism. Depending on the container the <auth-method> sub-level element can be delimited with commas as a fallback mechanism if the initial authentication method is unavailable. We discuss the four authentication types and the options available for each below.

BASIC AuthenticationTop

Basic authentication is the default and uses the Base64 algorithm to encrypt the user and password fields. Base64 is a weak encryption but is the HTTP standard so all browsers and containers support it. There is no need to code any programmatic security for basic authentication as HTTP provides the login mechanism. This also means that if your login screen is client facing this may not be an acceptable business choice. The <auth-method> sub-level element is optional and can only appear once within the top-level <login-config> element and should be set to BASIC (all uppercase) for basic authentication. The <realm-name> sub-level element is optional and can only appear once within the top-level <login-config> element and contains the registry used to store user account information or in the case of our test server a message to display on the login form. The following code snippet shows a DD entry for basic authentication.


<login-config>
   <auth-method>BASIC</auth-method>
   <realm-name>Authorized Users Only</realm-name>
</login-config>

DIGEST AuthenticationTop

Digest authentication is a much stronger encryption type than Base64 and generally uses the MD5 algorithm to encrypt the user and password fields. Digest authentication is an optional type for browsers and containers and so the interpretation and encryption can vary between vendors and so to use this authentication type effectively you need to make sure all your clients software is compatible. There is no need to code any programmatic security for the digest authentication, as if the browser supports digest, HTTP provides the login mechanism. This also means that if your login screen is client facing this may not be an acceptable business choice. The <auth-method> sub-level element can only appear once within the top-level <login-config> element and should be set to DIGEST (all uppercase) for digest authentication. The <realm-name> sub-level element is optional and can only appear once within the top-level <login-config> element and contains the registry used to store user account information. The following code snippet shows a DD entry for digest authentication.


<login-config>
   <auth-method>DIGEST</auth-method>
   <realm-name>Authorized Users Only</realm-name>
</login-config>

FORM AuthenticationTop

Form-based authentication allows us to customize the appearance of a login page that is customer facing. When declaring this type of authentication we also have to include an error page; both pages can be HTML or JSP pages. When using FORM authentication on initial entry to a constrained resource the login page is displayed. If the login is successful the constrained resource is sent, otherwise the user is sent the error page. The <auth-method> can only appear once within the top-level <login-config> element and should be set to FORM (all uppercase) for form-based authentication. The <form-login-config> must be present, is only applicable to the FORM authentication type and can only appear once within the the top-level <form-login-config> element. Within <form-login-config>, the <login-config-page> and <login-error-page> sub-level elements are both mandatory, must appear only once and represent HTML or JSP pages to display where appropriate. The following code snippet shows a DD entry 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>

CLIENT-CERT AuthenticationTop

Client certificate authentication uses digital certificates to achieve authentication. This method of authentication uses private/public key cryptography between the concerned parties. The private key is held safely by the digital certificate owner who can be trusted as their certificate has been digitally signed by a trusted certificate issuer. The digital certificate owner can then publish his public key knowing that any transmissions he receives can only be decrypted by his private key and also that any transmissions he sends using his private key can only be decrypted via the public key. This makes client certificate authentication the most protective authentication mechanism but also the hardest to set up initially. The following code snippet shows a DD entry for client certificate authentication.


<login-config>
   <auth-method>CLIENT-CERT</auth-method>
</login-config>

AuthorizationTop

Authorization works alongside authentication and allows us as programmers to decide which parts of our web application are available to which users (roles) using constraints declared within the DD. For example we may want our user to be able to browse through our goods and then enforce security if they want to buy something. This is done declaratively using the <security-constraint> top-level element which encompasses three sub-level elements, <web-resource-collection>, <auth-constraint> and <user-data-constraint> all of which can contain sub-level elements. We look at each of these elements in much greater detail below and the rules which apply to them.

The <web-resource-collection> ElementTop

Every <security-constraint> and you can have many, must contain at least one <web-resource-collection> sub-level element, which can itself consist of up to four sub-level elements these being; <web-resource-name> which is mandatory, appears once and has no specific function apart from describing the group being collected together. The optional <description> sub-level element which can be repeated as often as you want to describe this web resource collection. The <url-pattern> which is mandatory, can appear once or many times and works the same as all the other URL pattern matchers we have seen. Finally there is the <http-method> which is optional and can be repeated as often as you wish to constrain which type of http methods can be used.

  • Valid values for <http-method> are DELETE, GET, HEAD, OPTIONS, POST, PUT and TRACE and be all uppercase.
  • If any HTTP method is specified then all other HTTP methods not specified that your servlet supports are unconstrained and can be accessed by anyome regardless of the roles specified in <auth-constraint>.
  • If no HTTP methods specified all HTTP methods are constrained and can only be accessed by the roles specified in <auth-constraint>.

The following code snippet shows a single security constraint containing a web resource collection.


<security-constraint>
   <web-resource-collection>
      <web-resource-name>ViewBooks</web-resource-name>
      <url-pattern>/</url-pattern>
      <http-method>GET</http-method>
   </web-resource-collection>
</security-constraint>

The <auth-constraint> ElementTop

Every <security-constraint> can contain 0 or 1 <auth-constraint> sub-level element, which can itself consist of up to two sub-level elements these being; the optional <description> sub-level element which can be repeated as often as you want to describe this authority constraint. The optional <role-name> sub-level element which can be repeated as often as you want and specifies the roles allowed to access the constraints held within the <web-resource-collection> element. The <auth-constraint> element must follow the <web-resource-collection> element.

The following code snippet shows a single security constraint containing a web resource collection and the authentication constraint highlighted.


<security-constraint>
   <web-resource-collection>
      <web-resource-name>ViewBooks<web-resource-name>
      <url-pattern>/</url-pattern>
      <http-method>GET</http-method>
   </web-resource-collection>

   <auth-constraint>
      <role-name>tomcat</role-name>
      <role-name>role1</role-name>
   </auth-constraint>
</security-constraint>

The <user-data-constraint> ElementTop

Every <security-constraint> can contain 0 or 1 <user-data-constraint> sub-level element, which can itself consist of up to two sub-level elements these being; the optional <description> sub-level element which can be repeated as often as you want to describe this authority constraint. The mandatory <transport-guarantee> which must appear only once.

If present the <user-data-constraint> sub-level element must follow the <web-resource-collection> and <auth-constraint> sub-level elements.

Valid values for the mandatory <transport-guarantee> sub-level element are as follows:

  • NONE - Which is the default and means the data is not protected during transit.
  • INTEGRAL - Which means the data must not be modified during transit.
  • CONFIDENTIAL Which means the data must be hidden from view during transit.

The following code snippet shows a single security constraint containing a web resource collection, an authentication constraint and the user data constraint highlighted.


<security-constraint>
   <web-resource-collection>
      <web-resource-name>ViewBooks<web-resource-name>
      <url-pattern>/</url-pattern>
      <http-method>GET</http-method>
   </web-resource-collection>

   <auth-constraint>
      <role-name>tomcat</role-name>
      <role-name>role1</role-name>
   </auth-constraint>

   <user-data-constraint>
      <transport-guarantee>NONE</transport-guarantee>
   </user-data-constraint>
</security-constraint>

Data IntegrityTop

Data integrity is about ensuring that transmitted data is not intercepted by a third party and modified during transit. This is generally achieved using HTTPS over SSL, which acts as a protected transport layer and is available when using any compliant EE5 container.

We declare data integrity declaratively within the <transport-guarantee> sub-level element of the <user-data-constraint> sub-level element. The following code snippet shows how to declare data integrity.


<security-constraint>
   ...
   <user-data-constraint>
      <transport-guarantee>INTEGRAL</transport-guarantee>
   </user-data-constraint>
</security-constraint>

ConfidentialityTop

Confidentiality is a guarantee that transmitted data is kept private from any third party during transit. This is generally achieved using HTTPS over SSL, which acts as a protected transport layer and is available when using any compliant EE5 container. In practice this means that data integrity and confidentiality are achieved using the same process and achieve the same results regardless of the transport guarantee used.

We declare confidentiality declaratively within the <transport-guarantee> sub-level element of the <user-data-constraint> sub-level element. The following code snippet shows how to declare confidentiality.


<security-constraint>
   ...
   <user-data-constraint>
      <transport-guarantee>CONFIDENTIAL</transport-guarantee>
   </user-data-constraint>
</security-constraint>

Declaring Security RolesTop

The final part of declarative security involves declaring the security roles that are present in the vendor specific users file. To do this we use the top-level <security-role> element, which can itself consist of up to two sub-level elements these being; the optional <description> sub-level element which can be repeated as often as you want to describe the security roles present. The <role-name> sub-level element which is mandatory, can appear once or many times and mirrors the role names held in the vendor-specific users file which are in use for this web application.

The following code snippet shows an example of the top-level <security-role> element.


<security-role>
   <role-name>tomcat</role-name>
   <role-name>role1</role-name>
</security-role>

Example Of Declarative SecurityTop

Now we have seen all the aspects of declarative security it is time to see how we can use these DD entries to protect our web applications. To achieve this we will use the bookchoice web application we developed in the Session Management Part 3 lesson and change the DD within the deployed web application.

If you didn't do so earlier in the lesson change and save the tomcat-users.xml file by removing all the comments and uncommenting the file as below. In my case the tomcat-users.xml file can be found in:

C:\apache-tomcat-6.0.37\conf


<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
  <role rolename="tomcat"/>
  <role rolename="role1"/>
  <user username="tomcat" password="tomcat" roles="tomcat"/>
  <user username="both" password="tomcat" roles="tomcat,role1"/>
  <user username="role1" password="tomcat" roles="role1"/>
</tomcat-users>


Coding The DDTop

Go to your Tomcat installation for the the bookchoice web application, which in my case is:

C:\apache-tomcat-6.0.37\webapps\bookchoice\WEB-INF

Within the WEB-INF folder open up the web.xml file for editing and cut and paste the following XML, replacing the existing contents.


<?xml version="1.0" encoding="UTF-8"?>
<web-app xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
                             http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xmlns="http://java.sun.com/xml/ns/javaee" version="2.5">
   <servlet>
      <servlet-name>bookWishList</servlet-name>
      <servlet-class>controller.WishListServlet</servlet-class>
   </servlet>
   <servlet-mapping>
      <servlet-name>bookWishList</servlet-name>
      <url-pattern>/book</url-pattern>
      <url-pattern>/bookDetails</url-pattern>
      <url-pattern>/wishList</url-pattern>
   </servlet-mapping>
   
   <security-constraint>
      <web-resource-collection>
         <web-resource-name>ViewBooks</web-resource-name>
         <url-pattern>/</url-pattern>
         <http-method>GET</http-method>
      </web-resource-collection>

      <auth-constraint>
         <role-name>tomcat</role-name>
         <role-name>role1</role-name>
      </auth-constraint>
   </security-constraint>
   
   <security-role>
      <role-name>tomcat</role-name>
      <role-name>role1</role-name>
   </security-role>
   
   <login-config>
      <auth-method>BASIC</auth-method>
      <realm-name>Authorized Users Only</realm-name>
   </login-config>
</web-app>

Save the web.xml file in the WEB-INF folder.

Before we test the servlet we will go through the updated web.xml file and explain what we are trying to achieve with the security elements we have added. Within our security constraint we create a web resource collection with the name ViewBooks and are using the default match URL mapping to catch everything within this web applications context path. We are restricting access on the GET HTTP method so any other HTTP methods within the web application have unrestricted access.

We then specify the authentication constraints to be used in conjunction with our web resource collection so that only users with the role of tomcat and role1 can use the web application.

After this we specify the security roles in use for the the web application, which are tomcat and role1.

In Tomcat if you leave this element out the web application will still be protected but you will get a warning in the Tomcat logs for any authentication roles that have been constrained as follows:

No Security Role

Our final declarative specifies that we are going to use the BASIC authentication type and we will display the text Authorized Users Only on the login screen that is created by the HTTP 1.1 protocol

Testing Our ServletTop

Open a command prompt and change the directory to the location of our Tomcat bin directory and then type in startup (Windows 7) or startup.sh (Linux/Unix/OSX). Press Enter and the Tomcat server should open up in a new window.

You can also start up Tomcat by double-clicking the startup batch file within your Tomcat /bin folder.

With Tomcat up and running type the following into your web browser address bar and press enter:

  http://localhost:8080/bookchoice/book

The following screenshot shows the results of typing the above into the Chrome web browser address bar and pressing enter.

Authentication Screen 1

As you can see the browser has popped up an authentication screen for us to enter a username and password in.

To enter the application type in role1 or tomcat in the User Name: field and tomcat in the Password: field and press enter. You will then be able to use the application as you are now authenticated.

Layering SecurityTop

What if we wanted to layer our security so that all authenticated users can use the GET HTTP method but only certain users can use the POST HTTP method to add to a wish list, how would we go about this? Well we can add another security constraint to only allow users within a certain role to update wish lists. As we have already seen, this can be done declaratively using the DD.

Updating The DDTop

Go to your Tomcat installation for the the bookchoice web application, which in my case is:

C:\apache-tomcat-6.0.37\webapps\bookchoice\WEB-INF

Within the WEB-INF folder open up the web.xml file for editing and cut and paste the following XML, replacing the existing contents.


<?xml version="1.0" encoding="UTF-8"?>
<web-app xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
                             http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xmlns="http://java.sun.com/xml/ns/javaee" version="2.5">
   <servlet>
      <servlet-name>bookWishList</servlet-name>
      <servlet-class>controller.WishListServlet</servlet-class>
   </servlet>
   <servlet-mapping>
      <servlet-name>bookWishList</servlet-name>
      <url-pattern>/book</url-pattern>
      <url-pattern>/bookDetails</url-pattern>
      <url-pattern>/wishList</url-pattern>
   </servlet-mapping>
   
   <security-constraint>
      <web-resource-collection>
         <web-resource-name>ViewBooks</web-resource-name>
         <url-pattern>/</url-pattern>
         <http-method>GET</http-method>
      </web-resource-collection>

      <auth-constraint>
         <role-name>tomcat</role-name>
         <role-name>role1</role-name>
      </auth-constraint>
   </security-constraint>
   
   <security-constraint>
      <web-resource-collection>
         <web-resource-name>UpdateWishList</web-resource-name>
         <url-pattern>/wishList</url-pattern>
         <http-method>POST</http-method>
      </web-resource-collection>

      <auth-constraint>
         <role-name>tomcat</role-name>
      </auth-constraint>
   </security-constraint>
   
   <security-role>
      <role-name>tomcat</role-name>
      <role-name>role1</role-name>
   </security-role>
   
   <login-config>
      <auth-method>BASIC</auth-method>
      <realm-name>Authorized users only</realm-name>
   </login-config>
</web-app>

Save the web.xml file in the WEB-INF folder.

Before we test the servlet we will go through the updated web.xml file and explain what we are trying to achieve with the security elements we have added. We have added a new security constraint within which we create another web resource collection with the name UpdateWishList. We are using /wishList for URL mapping to catch entries that go to the wish list but are only restricting access on the POST HTTP method. So looking at the wish list using the GET HTTP method will work if the user is authenticated via the first security constraint.

We then specify the authentication constraints to be used in conjunction with our web resource collection so that only users with the role of tomcat can use the wish list when also using the POST HTTP method.

Retesting Our ServletTop

If yout Tomcat session is still open, close it so the new web.xml file gets deployed. Open a command prompt and change the directory to the location of our Tomcat bin directory and then type in startup (Windows 7) or startup.sh (Linux/Unix/OSX). Press Enter and the Tomcat server should open up in a new window.

You can also start up Tomcat by double-clicking the startup batch file within your Tomcat /bin folder.

With Tomcat up and running type the following into your web browser address bar and press enter:

  http://localhost:8080/bookchoice/book

When the browser has popped up an authentication screen for us to enter a username and password, type in role1 in the User Name: field and tomcat in the Password: field and press enter. You will then be able to use the application as you are now authenticated. If you try and add to the wish list you will get the following screen in Chrome:

Access Denied

This is just what we want for users with the role1 role, they can view via the first security constraint, but can't update because of the second security constraint.

Ok, to make sure users with the tomcat role can also update the wish list, close and reopen the browser window so we can redo authentication.

With Tomcat up and running type the following into your web browser address bar and press enter:

  http://localhost:8080/bookchoice/book

When the browser has popped up an authentication screen for us to enter a username and password, type in tomcat in the User Name: field and tomcat in the Password: field and press enter. You will then be able to use the application as you are now authenticated. If you try and add to the wish list there is no problem as you pass the authentication and authorization constraints.

Lesson 6 Complete

In this lesson we looked at securing our web applications declaratively.

What's Next?

In the next lesson we look at securing our web applications programmatically.

go to home page Homepage go to top of page Top