Creating WebLogger


Having absorbed all the filter technology discussed so far in this chapter, it's time to build WebLogger and start grabbing that user data when they come to your website. To let WebLogger get even more data about users, it's set up to handle users who log in using HTTP authentication, although that's optionalit also handles sites that don't use authentication, no problem.

Here's what this looks like. The web resource that WebLogger filters is called target.jsp, and if the user enters the URL for target.jsp, he'll see an HTTP authentication login dialog box, as shown in Figure 6.7.

Figure 6.7. Reading a password.


If the user enters the right password, he'll see target.jspas shown at the beginning of the chapter in Figure 6.1and his information will be logged to both a Tomcat log and another file named log.txt. The target.jsp file just displays a message, like this:

 <HTML>     <HEAD>         <TITLE>Welcome</TITLE>     </HEAD>     <BODY>         <CENTER>         <BR>         <BR>         <BR>         <H1>Welcome</H1>         <BR>         Welcome to this web page.         </CENTER>     </BODY> </HTML> 

WebLogger will store the user's name if he has been authenticated (as mentioned, authentication is optionalif your site doesn't use it, that's no problem). How do you set up HTTP authentication in case you want to use it? You have to edit a file of users on the web server; in Tomcat, that's called tomcat-users.xml, and you can find it in the Tomcat conf directory (back up this file before working on it, because if it gets messed up, Tomcat won't start).

For example, here's how you'd add a user named steve with the password "tomcat" to the users file:

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

This adds the user steve to the role named author. A role is something you make up; it's a group of users with similar functions, and you can grant or deny them access collectively.

For example, in the web.xml file, you can tell Tomcat that you're restricting access to target.jsp to those users who are part of the author role, like this:

 <?xml version="1.0" encoding="ISO-8859-1"?>         .         .         . <web-app>   <filter>     <filter-name>Simple Filter</filter-name>     <filter-class>Simple</filter-class>   </filter>         .         .         .   <filter-mapping>     <filter-name>Simple Filter</filter-name>     <url-pattern>/simple.jsp</url-pattern>   </filter-mapping>         .         .         .   <security-constraint>     <web-resource-collection>       <web-resource-name>Secure Area</web-resource-name>       <url-pattern>/target.jsp</url-pattern>     </web-resource-collection>     <auth-constraint>       <role-name>author</role-name>     </auth-constraint>   </security-constraint>   <login-config>     <auth-method>BASIC</auth-method>     <realm-name>Secure Area</realm-name>   </login-config> </web-app> 

The <login-config> element in web.xml indicates that this project uses the basic authentication method, which displays the kind of password-reading dialog box you see in Figure 6.7.

That sets up the user authentication if you want to use it. How do you create the WebLogger filter itself? Keep reading.

Collecting User Data

This filter logs user accesses and times, so Logger.java starts by creating a Date object that holds the current date and getting the current system time in milliseconds:

 import java.io.*; import java.util.*; import java.security.*; import javax.servlet.*; import javax.servlet.http.*; public final class Logger implements Filter {     public void doFilter(ServletRequest request,         ServletResponse response, FilterChain chain)         throws IOException, ServletException     {         Date date1 = new Date();         long start = System.currentTimeMillis();         .         .         .     }     public void destroy()     {     }     public void init(FilterConfig filterConfig)     {     } } 

Next in doFilter, you can get the user's IP address with the request object's getremoteAddr method, the URL the user is trying to reach with the request object's getrequestURI method, and the name of the user's host with the request object's geTRemoteHost method:

 public void doFilter(ServletRequest request,     ServletResponse response, FilterChain chain)     throws IOException, ServletException {     Date date1 = new Date();     long start = System.currentTimeMillis();     String address =  request.getRemoteAddr();     String file = ((HttpServletRequest) request).getRequestURI();     String host = ((HttpServletRequest) request).getRemoteHost();         .         .         . } 

You can also use the request object's getHeader method to read the User-Agent HTTP header to determine what browser the user has (after casting the ServletRequest object, you are passed in this method to an HttpServletRequest object):

 public void doFilter(ServletRequest request,     ServletResponse response, FilterChain chain)     throws IOException, ServletException {     String browser = "";     Date date1 = new Date();     long start = System.currentTimeMillis();     String address =  request.getRemoteAddr();     String file = ((HttpServletRequest) request).getRequestURI();     String host = ((HttpServletRequest) request).getRemoteHost();     if(((HttpServletRequest)request).getHeader         ("User-Agent").indexOf("MSIE") >= 0){         browser = "Internet Explorer";     }     if(((HttpServletRequest)request).getHeader         ("User-Agent").indexOf("Netscape") >= 0){         browser = "Netscape Navigator";     }         .         .         . } 

If the user has logged in using HTTP authentication, you can get the type of authentication (that's "basic" here) using the HttpServletRequest object's getAuthType method, and if that's not null, you can get the user's name by getting a Principal object and using that object's getName method:

 public void doFilter(ServletRequest request,     ServletResponse response, FilterChain chain)     throws IOException, ServletException {     String browser = "";     String authType = "none";     String username = "Not known";     Date date1 = new Date();     long start = System.currentTimeMillis();     String address =  request.getRemoteAddr();     String file = ((HttpServletRequest) request).getRequestURI();     String host = ((HttpServletRequest) request).getRemoteHost();         .         .         .     String type = ((HttpServletRequest)request).getAuthType();     if(type != null){         Principal principal =             ((HttpServletRequest)request).getUserPrincipal();         authType = type;         username = principal.getName();     }         .         .         . } 

Logging That Data

Now that you've gotten the data you need, how do you log it? One way is to use the FilterConfig object sent to the filter's init method. You can use this object's getServletContext method to get the servlet context, which is a common data space shared by the servlets and JSPs in the web application. The servlet context supports a log method, which can log text. Here's what that looks like in WebLoggerfirst, you save the FilterConfig object, access the servlet context, and then log your data:

 import java.io.*; import java.util.*; import java.security.*; import javax.servlet.*; import javax.servlet.http.*; public final class Logger implements Filter {     private FilterConfig filterConfig = null;     public void doFilter(ServletRequest request,         ServletResponse response, FilterChain chain)         throws IOException, ServletException     {         .         .         .     filterConfig.getServletContext().log(         "User access at " + date1.toString() +         " Authentication type: " + authType +         " User name: " + username +         " User IP: " + address +         " Accessing: " + file +         " Host: " + host +         " Browser: " + browser +         " Milliseconds used: " + (System.currentTimeMillis()         - start)     );         .         .         .     }     public void destroy()     {     }     public void init(FilterConfig filterConfig)     {          this.filterConfig = filterConfig;     } } 

This logs your data like so:

 User access at Mon Mar 07 15:47:53 EST 2005 Authentication type: BASIC User name: steve User IP: 127.0.0.1 Accessing: /logger/target.jsp Host: 127.0.0.1 Browser: Internet Explorer Milliseconds used: 109 

By default, this data goes to a file named stdout.log in the Tomcat log directory, and that's the way Logger.java works in the download for this book.

It's worth noting that you can also configure Tomcat so that your text will be sent to a log file of your choosing. For example, to store data in a Tomcat log named tomcat.log when you call the log method, you can use the popular Log4J package. Create a file called log4j.properties in the Tomcat common\classes directory and then put this text in it:

 log4j.rootLogger=debug, R log4j.appender.R=org.apache.log4j.RollingFileAppender log4j.appender.R.File=${catalina.home}/logs/tomcat.log log4j.appender.R.MaxFileSize=10MB log4j.appender.R.MaxBackupIndex=10 log4j.appender.R.layout=org.apache.log4j.PatternLayout log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n log4j.logger.org.apache.catalina=DEBUG, R 

For the Java support you'll need, download the Log4J package from http://logging.apache.org/log4j and then put Log4J JAR file in the Tomcat common\lib directory. Next, download the Commons Logging package from http://jakarta.apache.org/site/downloads/downloads_commons-logging.cgi and put commons-logging.jar in the Tomcat common\lib directory.

Doing this configures Tomcat to store your data in a file named tomcat.log when you pass text to the log method. It's a little extra work, but this way, your data isn't mixed in with a lot of Tomcat-specific messages.

Another way of logging your data is to do it yourself. For example, say that you're using Windows and want to log user data to a file named logs.txt in a directory named C:\logs. To do that, you can use a class such as Java's FileWriter class. The important methods of this class are inherited from the java.io.Writer class, which you can see in Table 6.4.

Table 6.4. Significant Methods of the java.io.Writer Class

Method

Does This

Writer append(char c)

Appends the given character to this writer

abstract void close()

Closes the output stream after flushing it

abstract void flush()

Flushes the stream

void write(char[] cbuf)

Writes an array of characters to the writer

abstract void write(char[] cbuf, int off, int len)

Writes a part of an array of characters to the writer

void write(int c)

Writes a single character to the writer

void write(String str)

Writes a string to the writer

void write(String str, int off, int len)

Writes part of a string to the writer


You can log the user data now by creating a new FileWriter object, then using the write method and the close method to close the FileWriter:

 public void doFilter(ServletRequest request,     ServletResponse response, FilterChain chain)     throws IOException, ServletException {     String browser = "";     String authType = "none";     String username = "Not known";     Date date1 = new Date();     long start = System.currentTimeMillis();     String address =  request.getRemoteAddr();     String file = ((HttpServletRequest) request).getRequestURI();     String host = ((HttpServletRequest) request).getRemoteHost();         .         .         .     String filename = "C:\\logs\\log.txt";     FileWriter filewriter = new FileWriter(filename, true);     filewriter.write("User access at " + date1.toString() +         "User access at " + date1.toString() +         " Authentication type: " + authType +         " User name: " + username +         " User IP: " + address +         " Accessing: " + file +         " Host: " + host +         " Browser: " + browser +         " Milliseconds used: " + (System.currentTimeMillis()         - start)     );     filewriter.close();         .         .         . } 

After logging the user's data, you have to call chain.doFilter to pass control on to target.jsp. Then you can add the message at the bottom of the results page indicating that the user's access has been logged:

 public void doFilter(ServletRequest request,     ServletResponse response, FilterChain chain)     throws IOException, ServletException {     String browser = "";     String authType = "none";     String username = "Not known";     Date date1 = new Date();     long start = System.currentTimeMillis();     String address =  request.getRemoteAddr();     String file = ((HttpServletRequest) request).getRequestURI();     String host = ((HttpServletRequest) request).getRemoteHost();         .         .         .     chain.doFilter(request, response);     response.setContentType("text/html");     PrintWriter out = response.getWriter();     out.println("<BR>");     out.println("<BR>");     out.println("<BR>");     out.println("<BR>");     out.println("<BR>");     out.println("<HR>");     out.println("<CENTER>");     out.println("<FONT SIZE = 2>");     out.println("<I>");     out.println("Your access to this page has been logged.");     out.println("</I>");     out.println("</FONT>");     out.println("</CENTER>"); } 

All that's left is to install this new filter in web.xml:

 <?xml version="1.0" encoding="ISO-8859-1"?>         .         .         . <web-app>         .         .         .   <filter>     <filter-name>Logging Filter</filter-name>     <filter-class>Logger</filter-class>   </filter>         .         .         .   <filter-mapping>     <filter-name>Logging Filter</filter-name>     <url-pattern>/target.jsp</url-pattern>   </filter-mapping>         .         .         . </web-app> 

When you run this project, the user's data will be sent to the stdout.log file as well as to the log.txt fileand you'll have the goods on him.

NOTE

Download the complete source code for the WebLogger project at the Sams website. After placing the needed files (Logger.class and web.xml) in the logger directory on your web server, as detailed in the beginning of the chapter, replace the name target.jsp in web.xml with the name of the web resource whose user accesses you want to log.




    Java After Hours(c) 10 Projects You'll Never Do at Work
    Java After Hours: 10 Projects Youll Never Do at Work
    ISBN: 0672327473
    EAN: 2147483647
    Year: 2006
    Pages: 128

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