如何使用JSF Servlet和其余Servlet记录每个URI访问 [英] How to log every URI access with the JSF servlet and the rest servlet

查看:189
本文介绍了如何使用JSF Servlet和其余Servlet记录每个URI访问的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用默认的JSF servlet和RestEasy servlet来服务URI请求(Wildfly 8.1).我希望使用@SessionScoped支持bean记录每个URI请求. CDI bean(@Named)或ManagedBean(@ManagedBean)都可以,以便我可以记录来自此访问者的http请求.

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.

我的要求:

  • 我不想从每个JSF页面调用访问记录, 也不来自每个REST资源Java文件.
  • 每个请求都必须可链接到@SessionScoped注释的后备bean Visit. Visit对象存储:
    • 用户(如果已识别)
    • 访问开始
    • 一个IP地址
    • 列表中的
    • n个URI请求:JSF资源请求和其余资源请求
    • 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

      我的问题:

      1. 如何在web.xml中注册一个过滤器以将两个请求(无论是JSF还是REST)都记录到@SessionScoped带注释的后备bean Visit?
      2. 如果我可以访问该支持bean,如何确保它是同一用户的会话?我不清楚该Web容器的会话管理. Web容器如何将请求映射到已知会话实例?默认使用Cookie吗?

      当然,在url模式/*上已经有一个servlet映射,而在/restresources/*上有一个servlet映射,一个不能为同一路径注册2个过滤器,可以吗? :

      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>
      

      推荐答案

      好的.对于其他想要记录每个页面和REST资源访问权限的人.

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

      在web.xml文件中创建过滤器.

      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>
      

      此外,创建过滤器类.

      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
          }
      }
      

      在这段代码中,我删除了重复请求的日志记录.仅记录jsf页面请求和REST资源请求.因此,没有图像,css或js请求.根据自己的需要调整RegEx.我已经用@Asynchronous注释了EJB函数saveUriRequest,以避免响应的延迟.

      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.

      回答我自己的问题:

      1. 过滤器将接收每个单个的HTTP请求-是JSF页面还是REST资源调用.用@Named和作为CDI bean注释Filter. @SessionScoped .现在,您将为每个访客提供一个过滤器.注意事项-如果您有大量不同的用户,请不要这样做.这将迅速唤醒您的可用内存.或者,您可以将其标记为@ApplicationScoped并从ServletRequest request标头实例获取访问者ID,并将请求分配给访问者.另外,这容易受到拒绝服务攻击. (我仅出于内部目的使用它.)
      2. 是的,Web容器在会话之间也通过jsessionid在ServletRequest request中进行分配.
      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.

      这篇关于如何使用JSF Servlet和其余Servlet记录每个URI访问的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆