4

我们正在使用 Apache Tomcat 7 并尝试设置 Valve 组件来存储我们的访问日志,以便在SnowPlow中进行处理。

我们遇到的问题是如何使这些日志变得健壮。举个例子 - 我们可以用标签分隔字段并提取用户代理字符串,如下所示:

pattern="%{yyyy-MM-dd}t	%{hh:mm:ss}t	%{User-Agent}i	"

问题是 Valve 组件没有(据我所知) escape %{User-Agent}i,所以用户代理中的杂散选项卡会破坏数据(行看起来包含四个字段,而不是三个)。

至于解决方案,除非有办法逃避我错过的用户代理,否则我可以看到几个解决方案:

  1. 使用不太可能出现在用户代理字符串中的非常模糊的字段分隔符(或字段分隔符的组合)。我们尝试了 Ctrl-A (HTML ?) 但这似乎不起作用
  2. 编写一个AccessLogValve支持转义或清理选项卡的自定义 - 可能类似于这篇文章Sanitizing Tomcat access log entries

有点困惑,我在网上找不到关于这个的任何其他信息 - 没有人解析他们的 Tomcat 访问日志吗?

你有什么建议吗?我们有点卡住了...

4

2 回答 2

1

RFC2616将用户代理字符串定义为

User-Agent     = "User-Agent" ":" 1*( product | comment )

那么产品定义为

product         = token ["/" product-version]
product-version = token

在此之后,令牌被定义为

token          = 1*<any CHAR except CTLs or separators>

和分隔符/ CTLs

separators     = "(" | ")" | "<" | ">" | "@"
                      | "," | ";" | ":" | "\" | <">
                      | "/" | "[" | "]" | "?" | "="
                      | "{" | "}" | SP | HT
CTL            = <any US-ASCII control character
                    (octets 0 - 31) and DEL (127)>

我们不需要忘记comment,它被定义为

comment    = "(" *( ctext | quoted-pair | comment ) ")" 
ctext      = <any TEXT excluding "(" and ")">
quoted-pair    = "\" CHAR
CHAR           = <any US-ASCII character (octets 0 - 127)>

所以如果我理解正确的话,你应该可以使用 any separatororCTL只要你能区分comment,它被包裹在(and中)。如果(出现在评论中,它应该用\.

于 2012-11-28T09:56:16.837 回答
0

最后,我编写了一个自定义的 Tomcat AccessLogValve,它:

  • 引入了一种新模式“I”来转义传入的标头
  • 引入了一种新模式“C”来获取存储在响应中的 cookie
  • 重新实现模式'i'以确保将“”(空字符串)替换为“-”
  • 重新实现模式“q”以删除“?” 并确保将“”(空字符串)替换为“-”
  • 覆盖了 'v' 模式,以写入此 AccessLogValve 的版本,而不是本地服务器名称

它似乎非常强大 - 我没有任何未转义值的进一步问题。

于 2013-07-28T21:09:05.350 回答