Client-Side Code Example

  

In this section, I develop an application to access project information of the XYZ Company. The user is required to sign in and is authenticated using a database realm. Based on the permissions granted, the project information is displayed.

The basic project information consists of a unique identifier, a name , and a description. The user has the option to view a project's detail (such as team members and the artifact associated with the project).

In addition:

  • If the user belongs to the finance group , financial information (initial quote, discount, and actual quote) is also displayed along with the project name and description.

  • If the user belongs to the admin group, there is an option to edit the project's information as follows :

    • If the user is an architect , the artifact information can be modified.

    • If the user is a manager , the name and description of the project as well as the team member information can be modifed.

    • If the user is in the finance group, the project quotes can be modifed.

Understanding the design

I decided to call this example the "Project Info App" and illustrate form authentication. I created a login.jsp , a logout.jsp , a fail_login.html, and a welcome.jsp to handle the form authentication based on a database realm. First, the user is asked to login via the login.jsp . If there is a problem, the fail_login.html page is displayed. If the user is authenticated, the welcome.jsp page is displayed.

Viewing the project

In the welcome screen the user has the choice to view the project list (other options could also be added). When the user makes the choice to view the projects, she is redirected to the ProjSelectionServlet, which retrieves all the project information (via a Project EJB) from a project database and displays the project list based on the user's permissions. If the user requests the project details, the ProjSelectionServlet redirects to the ProjectDetail.jsp .

Editing the project

However, if the user has admin rights and chooses to "edit" the project information, there is a redirection to the admin/editproject.jsp, where (based on the user rights) different project information may be modified. Once the information is modified, the user may submit it, at which time the editprojectServlet.java validates the information and commits it to the project database. At any time the user may select to end the session by the logout option on the pages. Figure 27-3 shows these components and their containers.

click to expand
Figure 27-3: Project Info App components and their corresponding containers

Working with user authentication

The first thing the user needs to do is log in to the application, which will be handled by a login JSP. In this example the JSP is called login.jsp, as shown in Figure 27-4.

click to expand
Figure 27-4: The login page for the Project Info App

Figure 27-4 shows how the login page looks running in a browser. The code for the page is given in Listing 27-3, the login.jsp file.

Listing 27-3: The login.jsp file for the Project Info App
start example
 <html>   <head> <title>XYZ's Projects Information</title> </head>  <body>   <blockquote>   <h1>XYZ's Project Information </h1>   <h2>Please enter your username and password:</h2>   <p>   <form method="POST" action="j_security_check">   <table border=1>     <tr> <td>Username:</td>      <td><input type="text" name="j_username"></td>     </tr>     <tr> <td>Password:</td>      <td><input type="password" name="j_password"></td>     </tr>     <tr> <td colspan=2 align=right><input type=submit value="Submit">  </td> </tr>   </table>  </form>  </blockquote> </body> </html> 
end example
 

If the user authentication fails (for example, if the password is wrong) an error page is displayed. Otherwise, the welcome page (shown in Figure 27-5) is displayed.

Cross-Reference  

Chapter 28 presents a brief discussion on entity beans and contains the Project entity bean code.

click to expand
Figure 27-5: The welcome page for the Project Info App

The welcome page is displayed by the welcome.jsp . If the user selects enter , the user is redirected to the ProjSelectionServlet via the following two lines of code:

 <form method="Get" action="jasaprjsel">  <td COLSPAN="2" ALIGN="right"> <input type="SUBMIT" VALUE="Enter"> </td> 

Working with the web.xml File

Listing 27-4 shows the web.xml file that supports this form-based login. It gives access to the admin directory to only those users that belong to the admin group and defines the <url-pattern> for Servlets used by JNDI lookup.

Listing 27-4: The web.xml file for the Project Info App
start example
 <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application  2.2//EN" "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd"> <web-app>   <display-name>Project Information</display-name>     <servlet>     <servlet-name>ProjSelectionServlet</servlet-name>     <servlet-class>com.richware.projinfo.ProjSelectionServlet</servlet- class>    </servlet> <servlet>     <servlet-name>editprojectServlet</servlet-name>     <servlet- class>com.richware.projinfo.admin.editprojectServlet</servlet-class>    </servlet>    <welcome-file-list>         <welcome-file>welcome.jsp</welcome-file>     </welcome-file-list>         <security-constraint>         <web-resource-collection>             <web-resource-name>AdminPages</web-resource-name>             <description>         The pages only accessible by authorized administrators.             </description>             <url-pattern>/admin/*</url-pattern>             <http-method>GET</http-method>         </web-resource-collection>         <auth-constraint>             <description>                 The roles with access             </description>             <role-name>                 admin             </role-name>         </auth-constraint>         <user-data-constraint>             <description>                 This is how the user data must be transmitted             </description>             <transport-guarantee>NONE</transport-guarantee>         </user-data-constraint>     </security-constraint>         <login-config>         <auth-method>FORM</auth-method>         <form-login-config>             <form-login-page>/login.jsp</form-login-page>             <form-error-page>/fail_login.html</form-error-page>         </form-login-config>     </login-config>         <security-role>         <description>             An administrator         </description>         <role-name>             admin         </role-name>     </security-role>      <servlet-mapping>      <servlet-name>ProjSelectionServlet</servlet-name>     <url-pattern>/jasaprjsel</url-pattern>   </servlet-mapping> <servlet-mapping>   <servlet-name>editprojectServlet</servlet-name>     <url-pattern>/jasaeditprj</url-pattern>   </servlet-mapping> </web-app> 
end example
 

Notice that I used form-based authentication but did not define a realm because I wanted to use the default realm. I added my users, defined my groups, added the appropriate users to the groups, and added the appropriate permission to the default realm. In a real application where you need more security, you can use more secure forms of authentication, such as JASA. In addition, throughout this example I use simple text request parameters to pass information among the different resources. As I mentioned earlier in this chapter, you probably do not want to use simple text, because it becomes obvious what technology is being used and may open the application to attacks.

Tip  

Using plain URIs may give a hint to a hacker about what technology is being used in your application, such a JSP or Servlet. You may want to map URI patterns using XML elements in the Web application's deployment descriptor and even encrypt them.

To verify whether a user can access a resource, you can also check programmatically if the user belongs to a group by calling the HttpServletRequest.isUserInRole() method. You can call this method from JSPs and Servlets. Listing 27-5 shows how this works in a Servlet.

Listing 27-5: A isUserInRole method example
start example
 if (req.isUserInRole("admin")) {        System.out.println("\n      user in admin group");       htmlCode.append("<td>Edit Option</td> \n");      } 
end example
 

In essence, you are combining the <security-role-ref> and <security-role> elements in the web.xml file. The way the users and groups are known by the Web container is container dependent. The <security-role-ref> element lets you use a role name in the isUserInRole method that is not defined by the < security-role> element.

Handling a user request

After the user is authenticated the welcome page is displayed and the user can select to Enter the application. This action redirects the user to the ProjSelectionServlet via a call to the Get method. This is handled by the service method on the Servlet.

The ProjSelectionServlet retrieves the project information from the project database by an EJB (the Project EJB) to display a table with the project information. In addition, the Servlet determines what options the user has by using the isUserInRole method to determine if the user is in the finance group and admin group. Listing 27-6 shows the ProjSelectionServlet class.

Listing 27-6: The ProjSelectionServlet class: The main page for the Project Info App
start example
 package com.richware.projinfo;     import java.io.*; import javax.servlet.*; import javax.servlet.http.*; import java.util.*; import javax.naming.Context; import javax.naming.InitialContext; import javax.rmi.PortableRemoteObject;     /**  * Class ProjSelectionServlet  * Description: The ProjSelectionServlet displays the main page  *  for this example.  * If the user has access, it displays the list of all projects  *  and their rates.  *  * Copyright:    Copyright (c) 2002  * Company:      HungryMinds  * @author Johennie Helton <jhelton@richware.com>  * @version 1.0   * DISCLAIMER: Please refer to the disclaimer at the beginning of this book. */     public class ProjSelectionServlet extends HttpServlet {   private ProjectHome projectHome;   private Vector projects;   /**   * Initialize the servlet with all the EJB home objects needed.   */  public void init(ServletConfig config) throws ServletException {     super.init(config);  try {         /*         * Use JNDI for the initialization parameters.         * Get the initial JNDI context & lookup the user home object         */          Context ctx = new InitialContext();          projectHome = (ProjectHome)ctx.lookup("projinfo.ProjectHome");         /*          * get all projects          */          Collection col = projectHome.findAll();          Iterator it = col.iterator();          this.projects = new Vector();          while (it.hasNext()) {           Project prjInfo = (Project)  PortableRemoteObject.narrow(it.next(), Project.class);            this.projects.addElement(prjInfo);          }       } catch (Exception e) {         getServletConfig().getServletContext().log(e," ");         throw new ServletException(e.toString());       } }   /**    * Service a request    */    public void service (HttpServletRequest req, HttpServletResponse  resp)     throws ServletException, IOException {      String urlStr = resp.encodeURL("jasaprojs");     /*      * make sure the user is authenticated. If not redirect to login      */      HttpSession session = req.getSession(false);      if(session == null) {        doRedirectToLogin(req,resp,"Please login first.");       return;      }      /**       * display the project list w/ a logout option at the top       */     resp.setContentType("text/html");     PrintWriter writer = resp.getWriter();     StringBuffer htmlCode = new StringBuffer();     htmlCode.append("<!doctype html public \"-//w3c/dtd HTML  4.0//en\">");     htmlCode.append("<% response.addHeader(\"Pragma\",\"No-cache\");  \n");     htmlCode.append("   response.addHeader(\"Cache-Control\",\"no- cache\"); \n ");     htmlCode.append("   response.addDateHeader(\"Expires\",1); %> \n");     htmlCode.append("<html> <head><title>Project  List</title></head>\n");     htmlCode.append("<body bgcolor=\"#FFFFFF\"> <center> <hr><br> &nbsp;  \n");     htmlCode.append("<h1> <font size=\"+2\" color=\"red\">Welcome to  XYZ's Projects</font> \n");     htmlCode.append("</h1> </center> <br> &nbsp; <hr> <br> &nbsp; \n");     htmlCode.append("<a href=logout.jsp>Logout</a>");     htmlCode.append("<table x:str border=1.0pt solid windowtext;");     htmlCode.append(" cellpadding=0 cellspacing=0 width=1111> <tr>");     htmlCode.append(" <td>Project ID</td> \n");     htmlCode.append(" <td>Project Name</td> \n ");     htmlCode.append(" <td>Project Description</td> \n");     // if the user has access to financial information show quotes and  discounts     if (req.isUserInRole("finance")) {       htmlCode.append("<td>Initial Quote</td> \n <td>Discount</td> \n");       htmlCode.append("<td>Actual Rate</td>  \n");     }    // if the user is an administrator then show edit choices    if (req.isUserInRole("admin")) {        htmlCode.append("<td>Edit Option</td> \n");      }     for (int i=0; i < projects.size(); i++){         Project prjInfo = (Project) projects.elementAt(i);         htmlCode.append("<tr> <td> <a  href=\"projectDetail.jsp?projid=");         htmlCode.append(prjInfo.getProjID());         htmlCode.append("&projname=");  htmlCode.append(prjInfo.getProjName());         htmlCode.append("\">");         htmlCode.append(prjInfo.getProjID());         htmlCode.append("</a>");         htmlCode.append("</td> <td> \n");         htmlCode.append(prjInfo.getProjName());         htmlCode.append("</td> <td> \n");         htmlCode.append(prjInfo.getProjDescription());         htmlCode.append("</td>");         if (req.isUserInRole("finance")) {           htmlCode.append("<td> \n");           htmlCode.append(prjInfo.getInitQuote());           htmlCode.append("</td> <td> \n");           htmlCode.append(prjInfo.getDiscount());           htmlCode.append("</td> <td> \n");           htmlCode.append(prjInfo.getActualRate());           htmlCode.append("</td>");         }         if (req.isUserInRole("admin")) {            htmlCode.append("<td> <a href=\"admin\editproj.jsp?projid=");   htmlCode.append(prjInfo.getProjID());           htmlCode.append("&projname=");  htmlCode.append(prjInfo.getProjName());          htmlCode.append("\">Edit</a> </td>");          }         htmlCode.append("</tr> \n");    }    htmlCode.append("</table>");    htmlCode.append("</form></body></html>");    writer.println(htmlCode.toString());    writer.close(); }    private void doRedirectToLogin(HttpServletRequest request,            HttpServletResponse response, String msg)     throws IOException, ServletException {     String url = "/login.jsp?errorMsg=" + msg;     response.sendRedirect(response.encodeURL(url)); } } 
end example
 

Figure 27-6 shows the resulting page from Listing 27-6 if the user is not an administrator.

click to expand
Figure 27-6: The Project List page for the Project Info App

If the user selects the Project ID column, the projectDetail.jsp page is displayed. Listing 27-7 shows the source code.

Listing 27-7: The projectDetail.jsp for the Project Info App
start example
 <!doctype html public "-//w3c/dtd HTML 4.0//en"> <html> <!-- The Project Detail Tables --> <head> <title>Project Detail</title> </head> <center> <h2> <font color=#DB1260>   <p>      <% String projname = request.getParameter("projname");         String projId = request.getParameter("projid");      %>     <strong>      <%= projname == null ? "": projname %>     </strong>     Project Details   </p> </font> </h2> </center> <p/><p/> <%@ page import=" weblogic.db.jdbc.*,  java.sql.* " %> <%! Connection conn  = null; String jdbcClass = "COM.cloudscape.core.JDBCDriver"; String jdbcURL   = "jdbc:cloudscape:demo"; public Connection getCon() {   try {    Driver myDriver = (Driver) Class.forName(jdbcClass).newInstance();     conn = myDriver.connect(jdbcURL, null);            } catch (Exception e) {}   return conn;  } %> <body> <% try {   conn = getCon();   if (conn != null) {     String selectTeam= "select EAUSER.* from PROJ_TEAM, EAUSER WHERE  PROJ_TEAM.projid = '" + projId + "' and EAUSER.userid =   PROJ_TEAM.userid";     Statement stmtTeam = conn.createStatement();     stmtTeam.execute(selectTeam);     ResultSet dsTeam = stmtTeam.getResultSet();       %>       <center><h2>Project Team </h2></center>       <table border=1 cellpadding=5>        <th>Department </th>        <th>Main contact </th> <%       while (dsTeam.next()) {         %>         <tr>          <td><%= dsTeam.getString("department") != null ?  dsTeam.getString("department") : "&nbsp;" %> </td>          <td><%= dsTeam.getString("name") != null ?  dsTeam.getString("name") : "&nbsp;" %></td>         </tr> <%       } %>             </table> <%     dsTeam.close();     String selectStm = "select ARTIFACT.* from ARTIFACT,PROJECT_ARTIFACT  WHERE PROJECT_ARTIFACT.projid = '" + projId + "' and  PROJECT_ARTIFACT.ARTIFACT_ID_VERSION = ARTIFACT.ARTIFACT_ID_VERSION";     Statement stmt = conn.createStatement();     stmt.execute(selectStm);     ResultSet ds = stmt.getResultSet();        %>       <center><h2>Project Artifacts </h2></center>       <table border=1 cellpadding=5>        <th>Artifact name </th>        <th>Artifact description </th>        <th>Artifact location</th> <%       while (ds.next()) {         %>         <tr>          <td><%= ds.getString("ARTIFACT_NAME") != null ?  ds.getString("ARTIFACT_NAME") : "&nbsp;" %> </td>          <td><%= ds.getString("ARTIFACT_DESCRIPTION") != null ?  ds.getString("ARTIFACT_DESCRIPTION") : "&nbsp;" %></td>          <td><%= ds.getString("ARTIFACT_LOCATION") != null ?  ds.getString("ARTIFACT_LOCATION") : "&nbsp;" %></td>         </tr> <%       } %>             </table> <%     ds.close();      conn.close();      out.flush();      }     else {      out.print("Sorry. Database is not available.");    }  } catch (Exception e) {   out.print("Exception: " + e); } %> <p> </body> </html> 
end example
 

The projectDetail.jsp uses JSP directives to import JDBC (I am using BEA's Weblogic). I also use JSP expressions to help determine what to display if a string is empty and to establish a connection to the database. In addition, I use JSP elements to retrieve the necessary information from the database and parse the result set to determine what needs to be presented to the user. Figure 27-7 shows the resulting HTML page from Listing 27-7.

click to expand
Figure 27-7: The Project Detail page for the Project Info App

In Figure 27-7 the user selected the Project Id 300-01 , called Death-Ray . These details are determined dynamically when the request is passed to the server and displayed along with the retrieved data from the database based on this selection.

The last detail that needs to be shown here is the admin/editproject.jsp , which handles the requests from an admin user. This is very similar to the projectDetail.jsp. Listing 27-8 shows part of the admin/editproject.jsp code.

Listing 27-8: The admin/projectedit.jsp for the Project Info App
start example
 <tr> <td>Project Name: </td>   <%= ds.getString("name") != null ? ds.getString("name") : "&nbsp;" %>  <% if (request.isUserInRole("manager")) { %>   <td> Change to: <input type="text" name="projname"> </td>  <% } %>        </tr> <tr> <td>Project Description: </td>  <%= ds.getString("DESCRIPTION") != null ? ds.getString("DESCRIPTION") :  "&nbsp;" %>  <% if (request.isUserInRole("manager")) { %>   <td> Change to: <input type="text" name="projdesc"> </td>  <% } %>         </tr>  <% if (request.isUserInRole("finance")) { %>   <tr> <td>Inital Quote: </td>   <%= ds.getString("initquote") != null ? ds.getString("initquote") :  "&nbsp;" %>   <% if (request.isUserInRole("manager")) { %>    <td> Change to: <input type="text" name="iquote"> </td>    <% } %>                 </tr> 
end example
 

Listing 27-8 shows how the editproject.jsp uses isUserInRole to determine if the information needs to be displayed (in the case of finance ) and if it needs to be editable (in the case of manager ). The rest of the code is very similar to Listing 27-7 and is omitted here.

  


Java Security Solutions
Java Security Solutions
ISBN: 0764549286
EAN: 2147483647
Year: 2001
Pages: 222

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net