How to log every URI access with the JSF servlet and the rest servlet

…衆ロ難τιáo~ 提交于 2019-12-12 04:54:04

问题


I'm using a default JSF servlet and RestEasy servlet to serve URI requests (Wildfly 8.1). I want every single URI request to be logged with a @SessionScoped backing bean. Either CDI bean (@Named) or ManagedBean (@ManagedBean) so that I can log the http requests from this visitor.

My requirements:

  • I don't want to invoke the logging of the access from each JSF page, nor from each REST Resource Java file.
  • Every request must be linkable to @SessionScoped annotated backing bean Visit. The Visit object stores:
    • a user (if identified)
    • start of visit
    • an IP Address
    • n URI requests in a list: JSF resource requests and rest resource requests

My questions:

  1. How do I register a filter in web.xml that logs both requests - be it JSF or REST - to the @SessionScoped annotated backing bean Visit?
  2. If I could access this backing bean, how do I ensure that it is the session fo the same user? This session management of the web container is unclear to me. How does the web container map the request to a known session instance? By a default cookie?

Of course there is already a servlet-mapping on the url-pattern /* and one on /restresources/* One could not register 2 filters for the same path, could you? :

<filter>
    <filter-name>UriLogger</filter-name>
    <filter-class>com.doe.filters.UriAccessLogger</filter-class>
</filter>
<filter-mapping>
    <filter-name>UriLogger</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

回答1:


Okay. For others that want to log every page and REST resource access, too.

Create the filter in the web.xml file.

<filter>
    <filter-name>UriLogger</filter-name>
    <filter-class>com.doe.filters.UriLoggingFilter </filter-class>
</filter>
<filter-mapping>
    <filter-name>UriLogger</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Also, create the filter class.

package com.doe.webapp.controller.general.filters;

import java.io.IOException;
import java.io.Serializable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.enterprise.context.SessionScoped;
import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.Logger;

import com.doe.webapp.controller.general.VisitController;

@Named
@SessionScoped
public class UriLoggingFilter implements Serializable, Filter {

    private static final long serialVersionUID = 1472782644963167647L;
    private static Logger LOGGER = Logger.getLogger(UriLoggingFilter.class);
    private String lastLoggedUri = "";

    FilterConfig filterConfig = null;
    @Inject
    VisitController visitController;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
    }

    /**
     * Log requests of interest with the VisitController.
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException,
            ServletException {

        // Run the other filters.
        filterChain.doFilter(request, response);

        if (request instanceof HttpServletRequest) {
            HttpServletRequest httpServletRequest = (HttpServletRequest) request;
            String uri = httpServletRequest.getRequestURI();

            String regex = "((/{1}\\w+$)|(/{1}\\w+\\.jsf$))";
            Pattern p = Pattern.compile(regex);
            Matcher m = p.matcher(uri);
            while (m.find()) {
                LOGGER.info("match " + m.group());

                if (!lastLoggedUri.equals(uri)) {
                    visitController.saveUriRequest(httpServletRequest);
                    lastLoggedUri = uri;
                } else {
                    LOGGER.warn("Multiple URI access to the same resource of the same user: " + uri);
                }
                break;
            }
        }

    }

    @Override
    public void destroy() {
        // TODO Auto-generated method stub
    }
}

In this code I removed the logging of repetitive requests. Only jsf page requests and REST resource requests are logged. Thus, no images, css or js requests. Adapt the RegEx according to your own needs. The EJB function saveUriRequest I have annotated with @Asynchronous, to avoid laggy delays of the response.

Answering my own questions:

  1. The filter will pick up every single http request - be it a JSF page or REST resource call. Annotate the Filter as a CDI bean with @Named and @SessionScoped. Now you have a filter for every single visitor. A WORD OF CAUTION - DON'T DO THIS IF YOU HAVE HIGH NUMBER OF DIFFERENT USERS. THIS WILL RAPIDLY BRING DOWN YOUR AVAILABLE MEMORY. Alternatively you could mark it as @ApplicationScoped and get a visitor id from the ServletRequest request header instance and assign the request to a visitor. Also, this is prone to Denials-Of-Service attacks. (I'm using this only for internal purpose.)
  2. Yes, the web container distriguishes between sessions by a jsessionid also from the ServletRequest request.

Hope this helps someone, too.



来源:https://stackoverflow.com/questions/26401368/how-to-log-every-uri-access-with-the-jsf-servlet-and-the-rest-servlet

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!