Securing Java Web Applications
Securing Java Web Applications
Introduction
For many web sites security is a primary concern. This is certainly no less true for a Java J2EE Web Application (and is probably even more true!). Traditionally security to such web sites has been controlled either programmatically be the developer or by the web server. With the advent of the Java Servlet version 2.3 specification declarative web container managed security has been introduced. This greatly enhances the developers ability to secure and control access to a Java Web Application in a web container and operating system independent manner.
web reosurce
Realm Interface
Memory Realm
JDBC Realm
JNDI Realm
Authentication information
In Tomcat 4.0.1 (the current release at time of writing and the reference implementation for the Servlet and JSP specifications), the way in which the web container obtains the user information is via a security realm. A realm is authentication system provider. In Tomcat a Realm is in fact a Java interface called org.apache.catalina.Realm. Note that Catalina is the codename for the Servlet engine used within Tomcat. The Realm interface is implemented by different authentication implementations. These implementations can then be plugged into the web container as required. In the case of Tomcat 4.0.1 (the current release version) three different Realm are provided by default These are an in-memory security realm (which is the default), a JDBC based one and a JNDI based system that allows any directory service that can be accessed via JNDI to be used (for example LDAP, Kerberos etc.). This is illustrated in Figure 1 and discussed below: In-Memory Realm. This is an in-memory data structure that is created using information provided in a XML fie. The default XML file is the conf/tomcat-users.xml file. This file can have users, their passwords and roles defined in it. Alternatively separate XML files can be created for individual applications. Again they can define users, passwords and roles but these are only available for a specific web application. They are defined using the context element in the conf/server.xml file of the Tomcat home directory. Note that as the XML file defining the users is loaded once when the server starts up, if new users are added to the file or details of existing users changed then these changes will not take affect until the Tomcat server is restarted. JDBC Realm. This is really a basic authentication system and interface to any JDBC compliant data source. That is, anything that provides a JDBC driver can be used as the repository for the authentication system information. If the JDBC realm is being used, then tables need to be created in a database system that contain the user id and password and the user id and roles. The JDBC Realm will then query the database via JDBC to obtain the user ids, passwords and roles. This is a much more preferable solution than the in-memory approach. This is for two reasons firstly user data is only loaded as and when needed. Secondly tools already available for the database system can be used to administer user ids, passwords and roles etc. In addition, Java based tools can be provided to provide application specific support. Note that once a users data is loaded it is not re-loaded from the database. Thus if a users has logged into the web applications, any subsequent changes to that users authentication profile will only take effect the next time the server is re-started. However, if a new users details are added to the database they are available immediately. JNDI Realm. The JNDI realm is the equivalent of the JDBC Realm but for resources that can be accessed via JNDI. Examples of such resources include LDAP and Kerberos. This realm operates in a similar manner to the JDBC realm. Thus new users are available immediately but changes to users who are already logged in will only take affect the next time the server is re-started.
In general the memory realm is suitable for small applications and prototypes. However larger real world application will need to use the JDBC or JNDI realms. Another option is to implement the Realm interface yourself and define your own realm.
Defining users
In the remainder of this chapter we will use the memory realm to access user data defined within the default tomcat-users.xml file. This is primarily because it is the simplest approach and therefore the easiest to follow. The basic idea will be the same for the other two realms supported by Tomcat. To learn about how to define the database tables required for the JDBC realm, or the entries required in a directory services for the JNDI realm, for see the tomcat web site. All users have a user id, a password and one or more roles associated with them. For example Figure 2 illustrates the tomcat-users.xml file with the users jjh and dec added. The user jjh has the password pop and the role eshopUsers. The user dec has the password bang and the roles eshopUsers and administrator. Note that these roles are case sensitive and that eShopUsers is not the same role as eshopUsers!
To use a different XML file for our web application (and thus the users, passwords and roles would only be available to that web application) we can configure the Context element for the web application. The Context element of the web application is defined in the conf/server.xml file. It allows the document base of the web application to be defined, the location of the web application to be specified, whether the application is reloadable by Tomcat and the realm to use. For example, see Figure 3.
Figure 3 indicates that the webshop web application will use the standard in memory real but that the file defining the users for this application is the webshop-users.xml file found in the WEB-INF directory of the webshop application.
Figure 4 illustrates an example of the <security-constraint> and <login-config> elements. Note that the Servlet and JSP declarations must come before the security details in the web.xml deployment descriptor. In this particular case the XML declarations state the following: The first part of the <security-constraint> element is the <web-resource-collection>. This element specifies that everything with the URL pattern starting webshop and fb will be part of the security realm for GET and POST operations. Thus the URL http//localhost:8080/webshop/enter will be within the secured area as its URL starts with the pattern webshop. Note we could have specified a single URL pattern, a complete path for a URL, just the GET method (GET, PUT, POST methods etc.). Next we need to state who can access these resources. This is done using the <auth-constraint> element. This element has one or more <role-name> sub elements that specify the roles that are allowed
to use these resources. In the example presented in Figure 4 eshopUsers and administrators are allowed to access these resources. Thus any user with the role eshopUsers or the role administrators (or both) can access the resource indicates by the URL http//localhost:8080/webshop/enter. Finally we need to indicate how information to be transferred between the clients browser and the web container. This is done using the <user-data-constraint> element. This element allows three values to be specified, NONE, INTEGRAL and CONFIDENTIAL.
The value NONE indicates that data can be sent as is. The value Integral indicates that the underlying data transmission should guarantee the integrity of the data during transmission. The value of CONFIDENTIAL indicates that the data should be not be observerable during transmission.
In practice INTEGRAL and CONFIDENTIAL usually both map to SSL transmission of the data. The <login-config> element allows the authentication method to be specified by the <auth-method> element and the <realm-name> to be specified. The authentication method can be one of BASIC, FORM, DIGEST and CLIENT (discussed in the next section). In the cases of a basic form, a simple login form similar to that presented in Figure 5 is displayed. This is an auto-generated form that uses a standard layout. The realm name is the name used when presenting the auto-generated login form to the user.
Authentication and Form-based authentication. Each of these will be discussed in more detail below. Basic Authentication relies on the web browser to generate a login form for the user when requested by the web container. The user then enters their user id and password into a simple dialog box that is only customisable via the Realm name. An example of the type of dialog generated by IE 5.5 is presented in Figure 5. No encryption is used for the user id or password, however it can be combined with the <user-data-constraint> element of the security constraint to use SSL. Digest Authentication is essentially the same as basic authentication except that the password is encrypted before transmission. This encryption is performed using a hashing algorithm such as MD5. This approach is more secure than the BASIC authentication as the password is not sent in plain text form. HTTPS Client authentication relies on the use of public key certificates and HTTPS to authenticate client systems. This approach is most appropriate in Business-toBusiness (B2B) systems. Using this approach the client and server must both prove who they are using a digital certificate. The subsequent communication of information is then performed using HTTPS. In this approach there is not even any need for a login screen as such as the login information is sent automatically. Form-based authentication is most similar to BASIC authentication. The difference is that it allows the developer to define their own login and error form. We have already seen an example of BASIC authentication, therefore we will now have a look at an example of FORM-based authentication. Figure 6 illustrates a web.xml deployment descriptor configured to use FORM-based authentication for the webshop web application. This is done inside the <login-config> element using the<auth-method> element. If this element is used then a second element must also be provided that defines the login and error page forms. This is the <formlogin-config> element. For example: <auth-method> FORM </auth-method> <form-login-config> <form-login-page> /login.html </form-login-page> <form-error-page> /errorpage.html </form-error-page> </form-login-config> In this example the login page is provided by the file login.html and the error page by the file errorpage.html. Note both could be HTML pages or both could be a Servlet or JSP.
Although there are no constraints on the format or either page, the form used to submit the login details does have some constraints specified in the Servlet 2.3 specification. These are that: The user id must be defined as a field of type text and called j-username. The password must be defined as a field of type password and be called j_password. The action associated with the form must be j_security_check. In actual fact j_security_check is a resource within the web container that implements the authentication. This is illustrated in Figure 7.
The result of accessing the URL protected by this login screen is presented in Figure 8.
For reference the result of incorrectly entering a user id or password is that the errorpage.html is presented. This is presented in Figure 9.
Conclusion
The security features added to the Servlet specification in version 2.3 are a major addition to the Java web application builders armory. As more web container vendors add this support to their systems we will wee this approach being used more and more by developers. Tomcat 4 provides an excellent reference implementation for these features that are likely to be mirrored in other containers.
Online References
Servlet 2.3 Specification and much more http://java.sun.com/products/servlet/ Java 2 Enterprise Edition Security Tutorial http://java.sun.com/j2ee/tutorial/1_3fcs/doc/Security.html The Liberty Alliance Project www.projectliberty.org