Logging POST Requests in a Spring Web Application




You want to log all POST requests, with all their parameters, but without leaking any passwords.


Spring has an abstract filter named AbstractRequestLoggingFilter, with two concrete implementations, but both of them log all requests. This means on every page load we get one log entry for each CSS / JS / PNG resource file (that is, every GET request). Being interested only in POST requests, we make our own implementation, which overrides the shouldLog method.

Also, our application may have some forms where users may change their passwords. We certainly don't want to log these, so if a request has a "password" parameter we'll want to apply some censorship.

public class PostRequestLoggingFilter extends AbstractRequestLoggingFilter {

	private static final String POST = RequestMethod.POST.toString();

	protected boolean shouldLog(HttpServletRequest request) {
		return logger.isDebugEnabled() && POST.equals(request.getMethod());

	protected void afterRequest(HttpServletRequest request, String message) {
		String censoredMessage = passwordRemover.removePassword(message);

An implementation of the PasswordRemover required in our logging filter may look like this:

public class RegExPasswordRemover implements PasswordRemover {

	 * Characters that may not appear unescaped in an URI:
	 * <pre>
	 * ! * ' ( ) ; : @ & = + $ , / ? # [ ]
	 * </pre>
	 * See <a href="https://tools.ietf.org/html/rfc3986#section-2.2">RFC 3986
	 * section 2.2 Reserved Characters</a>.
	private static final String URI_RESERVED_CHARACTERS = "!*'();:@&=+$,/?#[]";
	private static final Pattern PATTERN = Pattern
			.compile("(password|passwordAgain)=([^" + Pattern.quote(URI_RESERVED_CHARACTERS) + "]*)");

	private static final String REPLACEMENT = "***";

	public String removePassword(String uri) {
		 * In an URI, when encountering a parameter named "password" or "passwordAgain",
		 * replace its value with three stars (*).
		return PATTERN.matcher(uri).replaceAll("$1=" + REPLACEMENT);

For example, if the user submits a form with two fields: one containing their email address, someone@example.com and the other containing their password, secret, then the relevant part of the original log message would be:


The above implementation of the password remover would transform this into:


Show me the code

There's a complete example for the solution described above.


Spring's default logging filter
The list of reserved characters in an URI