Buscar este blog

viernes, 25 de marzo de 2016

Java servlet download log file

This is a basic servlet to download the log files of  a web app.
The servlet has the following config params:
  • logsConfigLocation. The base dir in which the log files are stored. It is not allowed to read files outside this directory.
  • logsMaxSize. The maximum size of the log file allowed to download
The config params can be configured usen Spring Expression Language, so a valid value could be ${my.config.property:/home/jboss/logs}
If none is specified, the default values are jboss.server.log.dir and 10MB respectively.


In order to prevent public access to this files, the servlet can be configured to use basic authentication. In this case, you need to configure the appropriate login mechanism in the app, form example, in web.xml:
<login-config>
 <auth-method>BASIC</auth-method>
 <realm-name>default</realm-name>
</login-config>

The servlet receives a request param called "path" which contains the relative route of the requested log file.

LoggerServlet:
package es.sisifo.jee6.servlet;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.HttpConstraint;
import javax.servlet.annotation.ServletSecurity;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.util.ServletContextPropertyUtils;


@WebServlet(urlPatterns = { "/loggerServlet" })
@ServletSecurity(@HttpConstraint(rolesAllowed = { "admin" }))
public class LoggerServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public static final String CONFIG_LOCATION_PARAM = "logsConfigLocation";
    public static final String CONFIG_MAXSIXE_PARAM = "logsMaxSize";

    private String logsLocation = System.getProperty("jboss.server.log.dir");
    private int maxFileSize = 10485760; // 10MB

    @Override
    public void init(final ServletConfig servletConfig) throws ServletException {
        super.init(servletConfig);

        if (servletConfig.getInitParameter(CONFIG_LOCATION_PARAM) != null) {
            logsLocation = ServletContextPropertyUtils.resolvePlaceholders(
                    servletConfig.getInitParameter(CONFIG_LOCATION_PARAM), servletConfig.getServletContext());
        }

        if (servletConfig.getInitParameter(CONFIG_MAXSIXE_PARAM) != null) {
            maxFileSize = Integer.valueOf(ServletContextPropertyUtils.resolvePlaceholders(
                    servletConfig.getInitParameter(CONFIG_MAXSIXE_PARAM), servletConfig.getServletContext()));
        }
    }


    @Override
    protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException,
            IOException {

        final String path = request.getParameter("path");
        if (!isValidPath(path)) {
            response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid path");
            return;
        }

        final File logFile = new File(logsLocation + File.separator + path);
        if (!isValidFile(logFile)) {
            response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid file");
            return;
        }

        downloadFile(logFile, response);
    }


    private void downloadFile(final File logFile, final HttpServletResponse response) throws IOException {
        final FileInputStream inStream = new FileInputStream(logFile);

        response.setContentType(getServletContext().getMimeType(logFile.getAbsolutePath()));
        response.setContentLength((int) logFile.length());
        response.setHeader("Content-Disposition", String.format("attachment; filename=\"%s\"", logFile.getName()));


        final OutputStream outStream = response.getOutputStream();

        final byte[] buffer = new byte[4096];
        int bytesRead = -1;
        while ((bytesRead = inStream.read(buffer)) != -1) {
            outStream.write(buffer, 0, bytesRead);
        }

        inStream.close();
        outStream.close();
    }


    private boolean isValidPath(final String path) {
        return path != null && !path.contains("..");
    }


    private boolean isValidFile(final File logFile) {
        return logFile.exists() && logFile.isFile() && logFile.length() <= maxFileSize;
    }
}

No hay comentarios:

Publicar un comentario