Analyser les requêtes HTTP avec les filtres de journaux Java
javax.servlet.FilterUn moyen pratique d'implémenter et d'analyser le contenu des requêtes HTTP et des journaux de sortie.FiltrePrésentation de la classe.
Ce filtre de journal utilise « java.util.logging.Logger » pour la sortie du journal et vous pouvez modifier la sortie des informations en modifiant le niveau de journalisation.
Qu'est-ce que javax.servlet.Filter ?
Lors de la création d'une application Web, en plus du traitement métier principal, il est nécessaire d'effectuer un traitement secondaire commun avant et après le traitement métier principal.
Par exemple, l'authentification du client, la vérification des autorités, la journalisation, etc.
Le codage d'un tel traitement secondaire dans chaque ressource devient une cause majeure d'entrave à la maintenabilité du logiciel, ce qui se traduit par une application difficile à maintenir.
En implémentant javax.servlet.Filter, vous pouvez généralement effectuer ce traitement secondaire avant que la requête ne soit transmise à la classe servlet.
De plus, étant donné que les paramètres de filtre peuvent être définis dans web.xml, vous pouvez ajouter ou supprimer des filtres de manière flexible sans modifier le code source.
Essayez d'utiliser un filtre de journal
Utilisons en fait un filtre de journal pour filtrer les requêtes HTTP et les analyser.
Cette foisMatouNous utiliserons l’application d’exemples disponible dès le début.
Vous pouvez exécuter ce filtre immédiatement en définissant les paramètres suivants.
2. Placez le fichier de classe compilé sous "/examples/WEB-INF/classes".
3.Définissez la définition suivante dans web.xml.
Filtre de journal Filtre de journal journalisation.Niveau BIEN Filtre de journal /*
*Le modèle d'URL lors de l'utilisation du framework Struts est le suivant.
*.faire
Veuillez vérifier les résultats de sortie du journal lors de l'exécution de l'écran Exemple de sessions.
Informations du journal de sortie et niveau de journalisation
●Contenu de la sortie du journal
Informations du journal | niveau de journalisation |
---|---|
Informations sur les cookies | BIEN |
Informations sur l'en-tête HTTP | BIEN |
HTTPAutres informations | BIEN |
Paramètres de requête HTTP | CONFIGURATION |
objet de portée de la demande | CONFIGURATION |
objet de portée session | CONFIGURATION |
Utilisation de la mémoire avant et après les requêtes | CONFIGURATION |
Informations sur la transition d'écran | INFO |
Il est préférable d'utiliser les niveaux de journalisation comme suit.
- FINE : génère le journal le plus détaillé. Définissez ceci si vous souhaitez analyser la requête HTTP en détail.
- CONFIG... Produit un journal quelque peu détaillé. C'est une bonne idée de le maintenir à ce niveau pendant la période de développement.
- INFO : Émet uniquement les informations de transition d’écran.
●Comment modifier le niveau de journalisation
Vous pouvez modifier le niveau de sortie du journal en définissant le paramètre d'initialisation logging.Level.
exemple:
journalisation.Niveau INFO
Code source
importer javax.servlet.Filter ;
importer javax.servlet.FilterChain ;
importer javax.servlet.FilterConfig ;
importer javax.servlet.ServletException ;
importer javax.servlet.ServletRequest ;
importer javax.servlet.ServletResponse ;
importer javax.servlet.http.Cookie ;
importer javax.servlet.http.HttpServletRequest ;
importer javax.servlet.http.HttpServletResponse ;
importer javax.servlet.http.HttpSession ;
/**
* Implémentez javax.servlet.Filter pour analyser le contenu des requêtes HTTP et des journaux de sortie
* Classe de filtre.
*/
la classe publique LogFilter implémente le filtre {
enregistreur statique privé enregistreur =
Logger.getLogger(LogFilter.class.getName());
chaîne finale statique privée LINE_SEPA =
System.getProperty("line.separator");
chaîne finale statique privée NEXT_PAGE = « LogFilter.NEXT_PAGE » ;
/**
* Initialisez ce filtre de journal.
* Cartographie @param
*/
public void init (mappage FilterConfig) {
String str = mapping.getInitParameter("logging.Level");
System.out.println("Définir le niveau de journalisation sur "+str+".");
Niveau niveau = nul ;
essayer {
niveau = Niveau.parse(str);
} attraper (Exception e) {
e.printStackTrace();
niveau = Niveau.INFO;
}
LogManager.getLogManager().reset();
Gestionnaire handler = new CustomConsoleHandler();
handler.setFormatter(nouveau CustomFormatter());
handler.setLevel(niveau);
logger.setLevel(niveau);
logger.getParent().addHandler(handler);
}
/**
* Il s'agit d'un filtre qui génère des journaux.
* @param request Requête HTTP en cours de traitement
* Réponse @param Réponse HTTP en cours de génération
* @chaîne param
*/
public void doFilter (ServletRequest _request, ServletResponse _response,
Chaîne FilterChain) lance IOException, ServletException {
// --------------------" Prétraitement "
Requête HttpServletRequest = (HttpServletRequest) _request ;
Réponse HttpServletResponse = (HttpServletResponse) _response ;
if (logger.isLoggable(Level.CONFIG)) {
enregistreur.config(
"============ Demande de démarrage !!"
+ « ID du fil de discussion : »
+ Thread.currentThread().hashCode()
+ ” ========================================================”);
}
// utilisation de la mémoire
Chaîne actionMemory = null ;
if (logger.isLoggable(Level.CONFIG)) {
actionMemory = getMemoryInfo(” ”
+ new Time(System.currentTimeMillis()) + ”Demande[précédent]”);
}
if (logger.isLoggable(Level.FINE)) {
logger.fine("Informations sur les cookies" + getCookieInfo(request));
}
if (logger.isLoggable(Level.FINE)) {
logger.fine("Informations d'en-tête HTTP" + getHeadersInfo(request));
}
if (logger.isLoggable(Level.FINE)) {
enregistreur
.fine("Autres informations HTTP" + getRequestOtherInfo(request));
}
if (logger.isLoggable(Level.CONFIG)) {
Chaîne reqlog = getRequestParametersInfo(request);
logger.config("Paramètres de requête HTTP" + reqlog);
}
if (logger.isLoggable(Level.CONFIG)) {
logger.config ("objet de portée de demande"
+ getRequestAttributeInfo(requête));
}
if (logger.isLoggable(Level.CONFIG)) {
Chaîne sessionlog = getSessionInfo(request,true);
logger.config ("objet de portée de session (avant le traitement de la demande)"
+ journal de session);
}
// appelle le filtre suivant
chain.doFilter(demande, réponse);
// ———————————————————- « Post-traitement »
if (logger.isLoggable(Level.CONFIG)) {
Chaîne sessionlog = getSessionInfo(request,false);
logger.config ("objet de portée de session (après traitement de la demande)"
+ journal de session);
}
// utilisation de la mémoire
if (logger.isLoggable(Level.CONFIG)) {
actionMemory = ”Utilisation de la mémoire avant et après la demande”+LINE_SEPA
+ actionMémoire + LINE_SEPA
+ getMemoryInfo(” ” + new Time (System.currentTimeMillis())
+ ”demande[après]”);
logger.config(actionMemory+LINE_SEPA);
}
// Informations sur la transition d'écran
if (logger.isLoggable(Level.INFO)) {
Chaîne nextPage = (String) request.getAttribute(NEXT_PAGE);
if (page suivante == null || nextPage.length() == 0) {
nextPage = request.getRequestURI();
}
logger.info("NEXT_PAGE=[" + page suivante + "], "
+ "IP_ADDRESS=[" + request.getRemoteAddr() + "], "
+ "SESSION_ID=[" + request.getSession().getId() + "], "
+ "USER-AGENT=[" + request.getHeader("user-agent") + "]");
}
if (logger.isLoggable(Level.CONFIG)) {
enregistreur.config(
"============ Fin de la demande !!"
+"ID du fil :"+ Thread.currentThread().hashCode()
+ ” =========================================================”
+LINE_SEPA+LINE_SEPA);
}
}
/**
*
*/
public void destroy() {
}
// ---------- Méthode privée ci-dessous -----------
chaîne statique privée getMemoryInfo (message de chaîne) {
DecimalFormat dFromat = nouveau DecimalFormat("#,###KB");
long libre = Runtime.getRuntime().freeMemory() / 1024 ;
total long = Runtime.getRuntime().totalMemory() / 1024 ;
long max = Runtime.getRuntime().maxMemory() / 1024;
utilisé longtemps = total – gratuit ;
Chaîne msg = message + ” : ” + “total =” + dFromat.format(total) + “, ”
+ « Montant utilisé = » + dFromat.format (utilisé) + » (« » + (utilisé * 100 / total)
+ « %), maximum disponible = » + dFromat.format(max);
renvoyer un message ;
}
/**
* Afficher tous les en-têtes de requête dans le journal.
*/
chaîne statique privée getHeadersInfo (requête HttpServletRequest) {
StringBuffer buff = nouveau StringBuffer(LINE_SEPA);
Enumération headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = (String) headerNames.nextElement();
buff.append(" ");
buff.append(headerName);
buff.append("=");
buff.append(request.getHeader(headerName));
buff.append(LINE_SEPA);
}
return buff.toString();
}
chaîne statique privée getCookieInfo (requête HttpServletRequest) {
StringBufferbuff = new StringBuffer();
Cookie[] cookies = request.getCookies();
si (cookies == nul) {
retour "";
}
pour (int i = 0; i < cookies.length; i++) {
buff.append("\n — Cookie[" + i + "] —\n");
buff.append(" ");
buff.append(cookies[i].getName());
buff.append("=");
buff.append(cookies[i].getValue());
buff.append(LINE_SEPA);
buff.append(" ");
buff.append("getVersion()");
buff.append("=");
buff.append(cookies[i].getVersion());
buff.append(LINE_SEPA);
buff.append(" ");
buff.append("getComment()");
buff.append("=");
buff.append(cookies[i].getComment());
buff.append(LINE_SEPA);
buff.append(" ");
buff.append("getDomain()");
buff.append("=");
buff.append(cookies[i].getDomain());
buff.append(LINE_SEPA);
buff.append(" ");
buff.append("getMaxAge()");
buff.append("=");
buff.append(cookies[i].getMaxAge());
buff.append(LINE_SEPA);
buff.append(" ");
buff.append("getPath()");
buff.append("=");
buff.append(cookies[i].getPath());
buff.append(LINE_SEPA);
buff.append(" ");
buff.append("getSecure()");
buff.append("=");
buff.append(cookies[i].getSecure());
buff.append(LINE_SEPA);
}
return buff.toString();
}
chaîne statique privée getRequestParametersInfo (requête HttpServletRequest) {
StringBuffer buff = nouveau StringBuffer(LINE_SEPA);
Carte map = convertRequest(requête);
TreeMap trr = new TreeMap(carte);
Itérateur itr = trr.keySet().iterator();
tandis que (itr.hasNext()) {
Clé de chaîne = (Chaîne) itr.next();
buff.append(" ");
buff.append(clé);
buff.append("=");
Valeur de l'objet = map.get(key);
Valeurs String[] = (String[]) valeur ;
si (valeurs.longueur == 1) {
buff.append(valeurs[0]);
} autre {
// Le tableau de chaînes est converti
String strValue = strate (valeurs);
buff.append(strValue);
}
buff.append(LINE_SEPA);
}
return buff.toString();
}
chaîne statique privée getRequestAttributeInfo (requête HttpServletRequest) {
StringBuffer buff = nouveau StringBuffer(LINE_SEPA);
Énumération e = request.getAttributeNames();
while (e.hasMoreElements()) {
Nom de la chaîne = (String) e.nextElement();
buff.append(" nom = " + nom + ", attributsClass = "
+ request.getAttribute(nom).getClass().getName()
+ ", toString() = " + request.getAttribute(nom)
+ LINE_SEPA);
}
return buff.toString();
}
chaîne statique privée getRequestOtherInfo (requête HttpServletRequest) {
StringBufferbuff = new StringBuffer();
buff.append(LINE_SEPA);
buff.append(”getCharacterEncoding()=");
buff.append(request.getCharacterEncoding());
buff.append(LINE_SEPA);
buff.append(”getContentLength()=");
buff.append(request.getContentLength());
buff.append(LINE_SEPA);
buff.append(”getContentType()=");
buff.append(request.getContentType());
buff.append(LINE_SEPA);
buff.append(”getLocale()=");
buff.append(request.getLocale());
buff.append(LINE_SEPA);
buff.append(”getProtocol()=");
buff.append(request.getProtocol());
buff.append(LINE_SEPA);
buff.append(”getRemoteAddr()=");
buff.append(request.getRemoteAddr());
buff.append(LINE_SEPA);
buff.append(”getRemoteHost()=");
buff.append(request.getRemoteHost());
buff.append(LINE_SEPA);
buff.append(”getScheme()=");
buff.append(request.getScheme());
buff.append(LINE_SEPA);
buff.append(”getServerName()=");
buff.append(request.getServerName());
buff.append(LINE_SEPA);
buff.append(”getServerPort()=");
buff.append(request.getServerPort());
buff.append(LINE_SEPA);
buff.append(”isSecure()=");
buff.append(request.isSecure());
buff.append(LINE_SEPA);
buff.append(”getAuthType()=");
buff.append(request.getAuthType());
buff.append(LINE_SEPA);
buff.append(”getContextPath()=");
buff.append(request.getContextPath());
buff.append(LINE_SEPA);
buff.append(”getMethod()=");
buff.append(request.getMethod());
buff.append(LINE_SEPA);
buff.append(”getPathInfo()=");
buff.append(request.getPathInfo());
buff.append(LINE_SEPA);
buff.append(”getPathTranslated()=");
buff.append(request.getPathTranslated());
buff.append(LINE_SEPA);
buff.append(”getQueryString()=");
buff.append(request.getQueryString());
buff.append(LINE_SEPA);
buff.append(”getRemoteUser()=");
buff.append(request.getRemoteUser());
buff.append(LINE_SEPA);
buff.append(”getRequestedSessionId()=");
buff.append(request.getRequestedSessionId());
buff.append(LINE_SEPA);
buff.append(”getRequestURI()=");
buff.append(request.getRequestURI());
buff.append(LINE_SEPA);
buff.append(”getServletPath()=");
buff.append(request.getServletPath());
buff.append(LINE_SEPA);
buff.append(”getUserPrincipal()=");
buff.append(request.getUserPrincipal());
buff.append(LINE_SEPA);
buff.append(”isRequestedSessionIdFromCookie()=");
buff.append(request.isRequestedSessionIdFromCookie());
buff.append(LINE_SEPA);
buff.append(”isRequestedSessionIdFromURL()=");
buff.append(request.isRequestedSessionIdFromURL());
buff.append(LINE_SEPA);
buff.append(”isRequestedSessionIdValid()=");
buff.append(request.isRequestedSessionIdValid());
buff.append(LINE_SEPA);
return buff.toString();
}
chaîne statique privée getSessionInfo (requête HttpServletRequest, booléen avant) {
Session HttpSession = request.getSession();
StringBufferbuff = new StringBuffer();
buff.append(LINE_SEPA);
si (avant) {
buff.append(” session.isNew() = ” + session.isNew());
buff.append(LINE_SEPA);
buff.append(” session.getId() = ” + session.getId());
buff.append(LINE_SEPA);
}
Énumération e = session.getAttributeNames();
while (e.hasMoreElements()) {
String sessionName = (String) e.nextElement();
Chaîne sessionClassName = session.getAttribute(sessionName)
.getClass().getName();
buff.append(" nom = " + nom de session + ", valeur = "
+ session.getAttribute(sessionName) + « ,attributClass = »
+ nom de classe de session + LINE_SEPA);
}
return buff.toString();
}
table de hachage statique privée convertRequest (requête HttpServletRequest) {
Table de hachage tempHash = new Hashtable();
Énumération e = request.getParameterNames();
while (e.hasMoreElements()) {
Clé de chaîne = (String) e.nextElement();
String[] valeurs = request.getParameterValues(key);
String[] paramètreValues = new String[values.length];
pour (int i = 0; i < valeurs.longueur; i++) {
paramètreValues[i] = convUnicode(values[i]);
}
tempHash.put(clé, paramètreValues);
}
retourner tempHash ;
}
Strate de chaîne statique privée (valeur de l'objet) {
si (valeur == null) {
renvoyer « nul » ;
} else if (valeur instanceof String[]) {
return convString((String[]) value);
} autre {
return value.toString();
}
}
/**
* Renvoie le contenu du tableau de chaînes [strArray] sous forme de chaîne comme celle ci-dessous.
* "[temp1, temp2, temp3]"
* @param strArray Tableau de chaînes à évaluer
* @return String après conversion
*/
chaîne statique privée convString(String[] strArray) {
si (strArray == null)
renvoie null ;
StringBufferbuff = new StringBuffer("[");
pour (int i = 0; i < strArray.length; i++) {
buff.append(strArray[i] + “, “);
}
buff.delete(buff.length() – 2, buff.length());
buff.append("]");
return buff.toString();
}
/**
* Convertissez [str] en Unicode.
* @param chaîne
* @retour
*/
chaîne statique privée convUnicode (chaîne str) {
si (str == nul)
renvoie null ;
essayer {
return new String(str.getBytes("8859_1"), "JISAutoDetect");
} catch (UnsupportedEncodingException e) {
lancer une nouvelle RuntimeException(e);
}
}
// ———————————————————————–
la classe statique CustomFormatter étend Formatter {
Modèle de chaîne final statique = « aaaa/MM/jj HH:mm:ss » ;
format de chaîne synchronisé public (enregistrement LogRecord) {
StringBuffer buf = new StringBuffer();
// définir la date et l'heure
Date date = nouvelle Date();
date.setTime(record.getMillis());
Formateur SimpleDateFormat = new SimpleDateFormat(motif);
buf.append(formatter.format(date));
buf.append(":");
// définit le niveau
buf.append("[" + record.getLevel().getName() + "]");
buf.append(":");
buf.append(record.getMessage());
buf.append(LINE_SEPA);
return buf.toString();
}
}
la classe statique CustomConsoleHandler étend StreamHandler {
public CustomConsoleHandler() {
super();
setOutputStream(System.out);
}
/**
* Émet un LogRecord.
* Initialement, les demandes de journalisation sont envoyées à un objet Logger.
* et cet objet initialise le LogRecord et
*Redirigé ici.
*
* @param record Description de l'événement de journal. les enregistrements nuls sont simplement ignorés
* et aucune notification ne sera envoyée.
*/
publication vide publique (enregistrement LogRecord) {
super.publish(enregistrement);
affleurer();
}
/**
* Remplacez StreamHandler.close par flush, mais
* Le flux de sortie n'est pas fermé. En d’autres termes, System.err n’est pas fermé.
*/
public void close() {
affleurer();
}
}
}