eu.eidas.node.AbstractNodeServlet.java Source code

Java tutorial

Introduction

Here is the source code for eu.eidas.node.AbstractNodeServlet.java

Source

/*
 * Copyright (c) 2015 by European Commission
 *
 * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
 * the European Commission - subsequent versions of the EUPL (the "Licence");
 * You may not use this work except in compliance with the Licence.
 * You may obtain a copy of the Licence at:
 * http://www.osor.eu/eupl/european-union-public-licence-eupl-v.1.1
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the Licence is distributed on an "AS IS" basis,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the Licence for the specific language governing permissions and
 * limitations under the Licence.
 *
 * This product combines work with different licenses. See the "NOTICE" text
 * file for details on the various modules and licenses.
 * The "NOTICE" text file is part of the distribution. Any derivative works
 * that you distribute must include a readable copy of the "NOTICE" text file.
 *
 */

package eu.eidas.node;

import eu.eidas.auth.commons.EIDASParameters;
import eu.eidas.auth.commons.EIDASUtil;
import eu.eidas.auth.commons.EIDASValues;
import eu.eidas.node.logging.LoggingMarkerMDC;
import eu.eidas.node.logging.LoggingUtil;

import org.slf4j.Logger;
import org.slf4j.MDC;
import org.springframework.context.ApplicationContext;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.util.Map;
import java.util.UUID;

/**
 * Generic EidasNode servlet ancestor.
 *
 * @author vanegdi
 * @since 1.2.2
 */
public abstract class AbstractNodeServlet extends HttpServlet {

    /**
     * Abstract logging impl.
     * @return the concrete logger of implementing servlet
     */
    protected abstract Logger getLogger();

    /**
     * Obtaining the application context
     * @return Node applicationContext
     */
    protected final ApplicationContext getApplicationContext() {
        return ApplicationContextProvider.getApplicationContext();
    }

    /**
     * Method used to renew the http session in traditional web application.
     *
     * @return the new session Id
     */
    private String sessionIdRegenerationInWebApp(HttpServletRequest request) {
        request.getSession(false).invalidate();
        String currentSession = request.getSession(true).getId();
        // Servlet code to renew the session
        getLogger().debug(LoggingMarkerMDC.SECURITY_SUCCESS,
                "Session RENEWED SessionIdRegenerationInWebApp [domain : {}][path {}][sessionId {}]",
                request.getServerName(), getServletContext().getContextPath(), currentSession);
        return currentSession;
    }

    /**
     * Creates a {@link java.util.Map} with all the parameters from the servletRequest, plus
     * the Remote Address, Remote Host, Local Address and Local Host. Then returns
     * the map.
     *
     * @return A map with the servletRequest's parameters, both the remote and
     *         local addresses and the remote and local host.
     *
     * @see java.util.Map
     */
    protected final Map<String, String> getHttpRequestParameters(HttpServletRequest request) {
        return EIDASUtil.getHttpRequestParameters(this.getClass().getCanonicalName(), request);

    }

    /**
     * Sets HTTPOnly Header on the session to prevent cookies from being accessed through
     * client-side script.
     *
     * @param renewSession indicates that the session cookie will be renewed
     */
    protected final void setHTTPOnlyHeaderToSession(final boolean renewSession, HttpServletRequest request,
            HttpServletResponse response) {
        if (request != null && request.getSession(false) != null) {
            // Renewing the session if necessary
            String currentSession = null;
            String messageLog = null;
            if (renewSession) {
                currentSession = sessionIdRegenerationInWebApp(request);
                messageLog = "http session Renewed : {}";
            } else {
                currentSession = request.getSession().getId();
                messageLog = "http session obtained from request : {}";
            }
            MDC.put(LoggingMarkerMDC.MDC_SESSIONID, currentSession);
            getLogger().info(LoggingMarkerMDC.SECURITY_SUCCESS, messageLog, currentSession);
            // changing session cookie to http only cookie
            if (request.getCookies() != null && request.isRequestedSessionIdFromCookie()) {
                //Session Id requested by the client, obtained from the cookie
                final String requestedSessionId = request.getRequestedSessionId();
                for (Cookie cookie : request.getCookies()) {
                    getLogger().debug("Treating cookie [domain][path][name][value] : [{}][{}][{}][{}]",
                            cookie.getName(), cookie.getPath(), cookie.getName(), cookie.getValue());
                    if (currentSession.equals(requestedSessionId)) {
                        // Removes old version
                        boolean isSecure = request.isSecure();
                        getLogger().debug("Cookie==session : Remove and replacing with HttpOnly {}",
                                cookie.toString());
                        getLogger().debug("Is using SSL?", isSecure);

                        //TODO: when migrating to servlet 3, use the cookie interface calls below instead of writing the http header
                        //
                        //NOSONAR                        cookie.setMaxAge(0);
                        //NOSONAR                        cookie.setPath(getServletContext().getContextPath());
                        //NOSONAR                 cookie.setDomain(request.getServerName());
                        //NOSONAR                 cookie.setSecure(isSecure);
                        //NOSONAR                 cookie.setHttpOnly(true);
                        //NOSONAR                 response.addCookie(cookie);

                        // Create new one httpOnly
                        StringBuilder httpOnlyCookie = new StringBuilder(cookie.getName())
                                .append(EIDASValues.EQUAL.toString()).append(cookie.getValue())
                                .append(EIDASValues.SEMICOLON.toString()).append(" ")
                                .append(EIDASValues.DOMAIN.toString()).append(EIDASValues.EQUAL.toString())
                                .append(request.getServerName()).append(EIDASValues.SEMICOLON.toString())
                                .append(" ").append(EIDASValues.PATH.toString())
                                .append(EIDASValues.EQUAL.toString()).append(getServletContext().getContextPath())
                                .append(EIDASValues.SEMICOLON.toString()).append(" ")
                                .append(EIDASValues.HTTP_ONLY.toString()).append(EIDASValues.SEMICOLON.toString())
                                .append(isSecure ? EIDASValues.SECURE.toString() : "");
                        response.setHeader(EIDASValues.SETCOOKIE.toString(), httpOnlyCookie.toString());
                    }
                }
            }
            //cookie _csrf
            //            request.setAttribute("_csrf_header", "X-CSRF-TOKEN");
            //            UUID idOne = UUID.randomUUID();
            //            LOG.info("generate csrf id="+idOne);
            //            request.setAttribute("_csrf", idOne);
            response.setHeader("_csrf_header", "X-CSRF-TOKEN");
            UUID idOne = UUID.randomUUID();
            UUID idTwo = UUID.randomUUID();
            getLogger().info("generate csrf id1=" + idOne + " id2=" + idTwo);
            Cookie gato = new Cookie("_csrf", idOne.toString());
            response.addCookie(gato);
            response.setHeader("X-CSRF-TOKEN", idTwo.toString());

        } else {
            getLogger().warn(LoggingMarkerMDC.SECURITY_FAILURE, "Request or Session is null !");
        }
    }

    /**
     * Encodes any given URL.
     *
     * @param url The URL to be encoded.
     *
     * @return The encoded URL.
     */
    protected final String encodeURL(final String url, HttpServletResponse response) {
        return response.encodeURL(url);
    }

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        LoggingUtil.logServletCall(request, this.getClass().getName(), getLogger());
        super.service(request, response);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        getLogger().warn(LoggingMarkerMDC.WEB_EVENT, "GET method invocation : possible spidering");
    }

    @Override
    protected void doHead(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        getLogger().warn(LoggingMarkerMDC.WEB_EVENT, "HEAD method invocation : possible spidering");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        getLogger().warn(LoggingMarkerMDC.WEB_EVENT, "POST method invocation : possible spidering");
    }

    @Override
    protected void doDelete(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        getLogger().warn(LoggingMarkerMDC.WEB_EVENT, "DELETE method invocation : possible spidering");
    }

    @Override
    protected void doPut(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        getLogger().warn(LoggingMarkerMDC.WEB_EVENT, "PUT method invocation : possible spidering");
    }

    @Override
    protected void doOptions(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        getLogger().warn(LoggingMarkerMDC.WEB_EVENT, "OPTIONS method invocation : possible spidering");
    }

    @Override
    protected void doTrace(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        getLogger().warn(LoggingMarkerMDC.WEB_EVENT, "TRACE method invocation : possible spidering");
    }

    protected final boolean acceptsHttpRedirect() {
        Boolean acceptGet = ApplicationContextProvider
                .getNodeParameterBool(EIDASParameters.ALLOW_REDIRECT_BINDING.toString());
        return acceptGet != null && acceptGet;
    }
}