/** * Copyright (c) Codice Foundation * <p> * This is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser * General Public License as published by the Free Software Foundation, either version 3 of the * License, or any later version. * <p> * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. A copy of the GNU Lesser General Public License * is distributed along with this program and can be found at * <http://www.gnu.org/licenses/lgpl.html>. */ package org.codice.ddf.platform.filter.clientinfo; import java.io.IOException; import java.util.HashMap; import java.util.Map; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import org.apache.shiro.util.ThreadContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This servlet filter extracts client-specific information and places it in the shiro {@link ThreadContext} * so it can be forwarded to useful areas of interest. Also contains the constants for working with * the client info map. * <p> * The information currently all comes from the servlet API; specifically a select few getters * within {@link javax.servlet.ServletRequest}. The format of the keys follows the format of java * beans. The keys are camel-cased names without the preceeding 'get' found in the method name. * <p> * For example, the key associated with {@link javax.servlet.ServletRequest#getRemoteAddr()} would * be the string {@code remoteAddr}. * <p> * The only exception to this rule, {@link ClientInfoFilter#CLIENT_INFO_KEY}, which holds a value string * of {@code client-info}, is the key used to access the entire client information map. It may contain * different kinds of data that does not necessarily correlate to the servlet API. */ public class ClientInfoFilter implements Filter { private static final Logger LOGGER = LoggerFactory.getLogger(ClientInfoFilter.class); public static final String CLIENT_INFO_KEY = "client-info"; public static final String SERVLET_REMOTE_ADDR = "remoteAddr"; public static final String SERVLET_REMOTE_HOST = "remoteHost"; public static final String SERVLET_SCHEME = "scheme"; public static final String SERVLET_CONTEXT_PATH = "contextPath"; @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void destroy() { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { ThreadContext.put(CLIENT_INFO_KEY, createClientInfoMap(servletRequest)); try { filterChain.doFilter(servletRequest, servletResponse); } finally { ThreadContext.remove(CLIENT_INFO_KEY); } } private Map<String, String> createClientInfoMap(ServletRequest request) { Map<String, String> clientInfoMap = new HashMap<>(); clientInfoMap.put(SERVLET_REMOTE_ADDR, request.getRemoteAddr()); clientInfoMap.put(SERVLET_REMOTE_HOST, request.getRemoteHost()); clientInfoMap.put(SERVLET_SCHEME, request.getScheme()); ServletContext servletContext = request.getServletContext(); if (servletContext != null) { clientInfoMap.put(SERVLET_CONTEXT_PATH, servletContext.getContextPath()); } LOGGER.debug("Creating client info map with the following pairs, {}", clientInfoMap.toString()); return clientInfoMap; } }