JavaServer Pages and servlets make several mechanisms available to Web developers to secure applications. Resources are protected declaratively by identifying them in the application deployment descriptor and assigning a role to them.
Several levels of authentication are available, ranging from basic authentication using identifiers and passwords to sophisticated authentication using certificates.
The authentication mechanism in the servlet specification uses a technique called role-based security. The idea is that rather than restricting resources at the user level, you create roles and restrict the resources by role.
You can define different roles in file tomcat-users.xml, which is located off Tomcat's home directory in conf. An example of this file is shown below −
<?xml version = '1.0' encoding = 'utf-8'?> <tomcat-users> <role rolename = "tomcat"/> <role rolename = "role1"/> <role rolename = "manager"/> <role rolename = "admin"/> <user username = "tomcat" password = "tomcat" roles = "tomcat"/> <user username = "role1" password = "tomcat" roles = "role1"/> <user username = "both" password = "tomcat" roles = "tomcat,role1"/> <user username = "admin" password = "secret" roles = "admin,manager"/> </tomcat-users>
This file defines a simple mapping between username, password, and role. Notice that a given user may have multiple roles; for example, username = "both" is in the "tomcat" role and the "role1" role.
Once you have identified and defined different roles, role-based security restrictions can be placed on different Web Application resources by using the <security-constraint> element in web.xml file available in the WEB-INF directory.
Following is a sample entry in web.xml −
<web-app> ... <security-constraint> <web-resource-collection> <web-resource-name>SecuredBookSite</web-resource-name> <url-pattern>/secured/*</url-pattern> <http-method>GET</http-method> <http-method>POST</http-method> </web-resource-collection> <auth-constraint> <description> Let only managers use this app </description> <role-name>manager</role-name> </auth-constraint> </security-constraint> <security-role> <role-name>manager</role-name> </security-role> <login-config> <auth-method>BASIC</auth-method> </login-config> ... </web-app>
The above entries would mean −
Any HTTP GET or POST request to a URL matched by /secured/* would be subject to the security restriction.
A person with the role of a manager is given access to the secured resources.
The login-config element is used to describe the BASIC form of authentication.
If you try browsing any URL including the /security directory, the following dialog box will be displayed asking for username and password. If you provide a user "admin" and password "secret", then you will have access on the URL matched by /secured/* as we have defined the user admin with manager role who is allowed to access this resource.
When you use the FORM authentication method, you must supply a login form to prompt the user for a username and password. Following is a simple code of login.jsp. This helps create a form for the same purpose −
<html> <body bgcolor = "#ffffff"> <form method = "POST" action ="j_security_check"> <table border = "0"> <tr> <td>Login</td> <td><input type = "text" name="j_username"></td> </tr> <tr> <td>Password</td> <td><input type = "password" name="j_password"></td> </tr> </table> <input type = "submit" value = "Login!"> </form> </body> </html>
Here you have to make sure that the login form must contain the form elements named j_username and j_password. The action in the <form> tag must be j_security_check. POST must be used as the form method. At the same time, you will have to modify the <login-config> tag to specify the auth-method as FORM −
<web-app> ... <security-constraint> <web-resource-collection> <web-resource-name>SecuredBookSite</web-resource-name> <url-pattern>/secured/*</url-pattern> <http-method>GET</http-method> <http-method>POST</http-method> </web-resource-collection> <auth-constraint> <description>Let only managers use this app</description> <role-name>manager</role-name> </auth-constraint> </security-constraint> <security-role> <role-name>manager</role-name> </security-role> <login-config> <auth-method>FORM</auth-method> <form-login-config> <form-login-page>/login.jsp</form-login-page> <form-error-page>/error.jsp</form-error-page> </form-login-config> </login-config> ... </web-app>
Now when you try to access any resource with URL /secured/*, it will display the above form asking for the user id and password. When the container sees the "j_security_check" action, it uses some internal mechanism to authenticate the caller.
If the login succeeds and the caller is authorized to access the secured resource, then the container uses a session-id to identify a login session for the caller from that point on. The container maintains the login session with a cookie containing the session-id. The server sends the cookie back to the client, and as long as the caller presents this cookie with subsequent requests, then the container will know who the caller is.
If the login fails, then the server sends back the page identified by the form-error-page setting
Here, j_security_check is the action that applications using form based login have to specify for the login form. In the same form, you should also have a text input control called j_username and a password input control called j_password. When you see this, it means that the information contained in the form will be submitted to the server, which will check name and password. How this is done is server specific.
Check Standard Realm Implementations to understand how j_security_check works for Tomcat container..
The HttpServletRequest object provides the following methods, which can be used to mine security information at runtime −
S.No. | Method & Description |
---|---|
1 | String getAuthType() The getAuthType() method returns a String object that represents the name of the authentication scheme used to protect the Servlet. |
2 | boolean isUserInRole(java.lang.String role) The isUserInRole() method returns a boolean value: true if the user is in the given role or false if they are not. |
3 | String getProtocol() The getProtocol() method returns a String object representing the protocol that was used to send the request. This value can be checked to determine if a secure protocol was used. |
4 | boolean isSecure() The isSecure() method returns a boolean value representing if the request was made using HTTPS. A value of true means it was and the connection is secure. A value of false means the request was not. |
5 | Principle getUserPrinciple() The getUserPrinciple() method returns a java.security.Principle object that contains the name of the current authenticated user. |
For example, for a JavaServer Page that links to pages for managers, you might have the following code −
<% if (request.isUserInRole("manager")) { %> <a href = "managers/mgrreport.jsp">Manager Report</a> <a href = "managers/personnel.jsp">Personnel Records</a> <% } %>
By checking the user's role in a JSP or servlet, you can customize the Webpage to show the user only the items she can access. If you need the user's name as it was entered in the authentication form, you can call the getRemoteUser method in the request object.