Security

Trouble larks every in every corner of the internet, your web site is exposed to millions of people good and bad, crackers, scammers and criminals will try and break into your system to steal, take advantage or just to have a little fun with your web site. You also have a responsibility to your customers to protect their data (credit card details, etc). There are three types of bad guys

The application server provides four types of servlet security

When a client using a browser accesses a web page, the Container will check to see if that page being requested has any security constraints, if it does then the client will be asked to authenticate (basically confirm who he/she actually is), this is generally done by requesting for a username and password. Once the client has been authenticated the Container will then make sure that particular client has access to that page (it could be a payroll page) this is the authorization part.

I have ready discussed Tomcat Security in great detail thus I will skim over it in this feature,

Authentication

Tomcat uses a concept called a realm, it is a place where authentication information is stored. Tomcat uses a file in the conf directory called tomcat-users.xml, this file is read into memory at startup time.

tomcat-users.xml <tomcat-users>
  <role rolename="Admin"/>
  <role rolename="Guest"/>
  <role rolename="Member"/>
  <user username="vallep" password="secret" roles="Admin,Member" />
  ...
</tomcat-users>

Like many software products Tomcat uses the concept of users and roles, roles are assigned to a particular web page and then the user is assigned a role. To enable authentication you need to update the DD (web.xml) to turn it on, then you need to define roles within your application.

turn on authentication (web.xml) <login-config>
  <auth-method>BASIC</auth-method>
</login-config>

<security-role>
  <role-name>Admin<role-name>
</security-role>

<security-role>
  <role-name>Member<role-name>
</security-role>

Now you are ready to lock down you application and again its in the DD (web.xml), I have locked down the entire application but you can be more pacific, also note that I stopped GET and POST http methods but there are several others. This means that the resource is constrained with a HTTP method (POST, GET, etc). To stop all methods simply leave out the <http-method> element. You can stop everyone from accessing the web page by simply leaving out the <role-name> within the <auth-constraint> element by the same turn you can give everyone access by using an asterisk (*).

securing a web app <web-app ...>
  <security-constraint>

    <web-resource-collection>

      <web-resource-name>Entire Application</web-resource-name>

      <url-pattern>/*</url-pattern>

      <http-method>GET</http-method>
      <http-method>POST</http-method>

    </web-resource-collection>

    <auth-constraint>
      <role-name>Admin</role-name>
      <role-name>Member</role-name>
    </auth-constraint>

  </security-constraint>

Although the above is a way to implement authentication (small environment), in the real world you probably would use a database or an LDAP server to hold the username information again, have a look at Tomcat Security which will describe on how to use a database to store your username/password.

If you have not already read my Tomcat Security feature then here are the four basic types of auth

BASIC Base64 - weak The BASIC authentication mechanism is simplistic, it has some serious problems as it uses Base64 which is not very secure and the browser caches credentials after authentication.
DIGEST Stronger - but not SSL DIGEST is the next set up, it is the same as BASIC but the password is transmitted in a secure fashion, it performs a digest on the password (one way hash) before sending it across the wire. It to has flaws the original password must be stored somewhere in plain text and it to suffers from the same browser caching problem. DIGEST can use either MD5 or SHA to hash the password.
Form Very Weak, no encryption The browser does not help with the authentication, instead it creates a HTML form where the username and password is entered and passed to the servlet container, this can be secured by using HTTPS. However it has one flaw where the username and password must be stored somewhere on the servlet container, normally in plain text.
HTTPS Client Certificate Strong - public key (PKC) When the browser establishes a connection, the browser is sent a public key certificate from the server, this certificate enables the browser to authenticate with the server. This enables the browser to know the true identity of the server as certified(signed) by a trusted third party (such as VeriSign). This is the most secure method but it too has flaw, if the key length used to encrypt the messages is to short then it becomes more vulnerable to attacks, also the theft of the private key would result in the authentication becoming compromised.

Within the <login-config> elements you have to choose one method, in the real world form based authentication is widely used, here is an example

Configuring Authentication <web-app ...>
  <security-constraint>
    <web-resource-collection>
      <web-resource-name>Entire Application</web-resource-name>
      <url-pattern>/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
      <role-name>manager</role-name>
    </auth-constraint>
  </security-constraint>
  <login-config>
    <auth-method>FORM</auth-method>
    <realm-name>My Test Application</realm-name>
    <form-login-config>
      <form-login-page>/login.html</form-login-page>
      <form-error-page>/error.html</form-error-page>
    </form-login-config>
  </login-config>
  ...
  <security-role>
    <role-name>manager</role-name>
  </security-role>
</web-app>
  
Authentication Form (login.html)

<html>
  <head><title>Please login</title>
  <body>
    <form method="POST" action="j_security_check">
      <table>
      <tr>
        <th>Username:</th>
        <td><input type="text" name="j_username"></td>
      </tr>
      <tr>
        <th>Password:</th>
        <td><input type="text" name="j_password"></td>
      </tr>
      <tr>
        <td><input type="submit" value="Log In"></td>
        <td><input type="reset"></td>
      </tr>
      </table>
    </form>
  </body>
</html>

Note: the Container will perform all the checks providing you use the correct action and names as above

tomcat-users.xml <tomcat-users>
  <role rolename="guest"/>
  <role rolename="manager"/>
  <role rolename="admin"/>
  <user username="vallep" password="secret" roles="admin,manager" />
  ...
</tomcat-users>

Authorization

You can also use programmatic security, by authenticating within the servlets code, there are three methods associated with programmatic security

isUserInRole() if( request.isUserInRole("Admin") ) {
   // do some stuff
} else {
   // you are not allowed to do some stuff
}

Although hard coding in the role is a terrible idea there may a possibility that someone has done it, the DD has a mechanism for mapping hard-coded roles in a servlet to the "official" <security-role> declarations in your Container, this means you don't have to search and change all the hard coded roles.

role mapping in the DD (web.xml)

<web-app...>
  <servlet>
    <security-role-ref>
      <role-name>Manager</role-name>
      <role-name>Admin</role-name>
    </security-role-ref>
  ...
  </servlet>
  ...
  <security-role>
    <role-name>Admin</role-name>
  </security-role>
</web-app>

Note: The DD is mapping Manager and Admin to the Admin role

Data Confidentiality & Integrity

You can also implement data confidentiality and integrity sparingly and declaratively by using the <user-data-constraint> element, see Encryption with SSL for more details.