/******************************************************************************* * Copyright 2014 Federal Chancellery Austria * MOA-ID has been developed in a cooperation between BRZ, the Federal * Chancellery Austria - ICT staff unit, and Graz University of Technology. * * 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/ * * 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 at.gv.egovernment.moa.id.configuration.filter; import java.io.IOException; import java.util.ArrayList; import java.util.Date; import java.util.StringTokenizer; import java.util.regex.Pattern; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import at.gv.egovernment.moa.id.config.webgui.exception.ConfigurationException; import at.gv.egovernment.moa.id.configuration.Constants; import at.gv.egovernment.moa.id.configuration.auth.AuthenticatedUser; import at.gv.egovernment.moa.id.configuration.auth.AuthenticationManager; import at.gv.egovernment.moa.id.configuration.config.ConfigurationProvider; import at.gv.egovernment.moa.util.MiscUtil; import at.gv.util.ToStringUtil; import at.gv.util.WebAppUtil; public class AuthenticationFilter implements Filter{ private final Logger log = Logger.getLogger(AuthenticationFilter.class); private static ConfigurationProvider config; public static final String STORED_REQUEST_URL_ID = String.class.getName() + ":" + "storedRequestURL"; public static final String WEB_XML_INIT_PARAM_LOGIN_PAGE = "loginPage"; public static final String WEB_XML_INIT_PARAM_ERROR_PAGE = "errorPage"; public static final String WEB_XML_INIT_PARAM_AUTHENTICATED_PAGE = "authenticatedPage"; // optional public static final String WEB_XML_INIT_PARAM_SESSION_LOST_PAGE = "sessionLostPage"; // optional public static final String WEB_XML_INIT_PARAM_ALLOWED_LIST = "allowedList"; public static final String WEB_XML_INIT_PARAM_ALLOWED_REGEX = "allowed"; private static final String WEB_XML_INIT_PARAM_EXCLUDED_PAGES_DELIMITER = ","; private static String loginPage = null; private boolean loginPageForward = true; private static String errorPage = null; private static String authenticatedPage = null; private static String sessionLostPage = null; private static String[] excludedPages = null; private static Pattern excludedRegEx = null; public static String getErrorPage() { return errorPage; } public static String getAuthenticatedPage() { return authenticatedPage; } public static String getLoginPage() { return loginPage; } public static String getSessionLostPage() { return sessionLostPage; } private boolean isExcluded(String url) { boolean excluded = false; if (MiscUtil.isNotEmpty(excludedPages)) { for (String candidate : excludedPages) { if (StringUtils.upperCase(url).endsWith(StringUtils.upperCase(candidate))) { excluded = true; break; } } } if (excludedRegEx != null && !excluded) { // log.debug("Trying to match regex \"{}\" with \"{}\".", // excludedRegEx.toString(), url); if (excludedRegEx.matcher(url).matches()) { excluded = true; } } log.debug("URL \"" + url + "\" is " + (excluded ? "" : "NOT ") + "excluded from filter."); return excluded; } public void destroy() { log.trace("Shutting down" + this.getClass().getName() + "..."); } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterchain) throws IOException, ServletException { HttpServletRequest httpServletRequest = (HttpServletRequest) req; HttpServletResponse httpServletResponse = (HttpServletResponse) resp; HttpSession session = httpServletRequest.getSession(); Object authuserobj = session.getAttribute(Constants.SESSION_AUTH); AuthenticatedUser authuser = (AuthenticatedUser) authuserobj; String requestURL = WebAppUtil.getRequestURLWithParameters(httpServletRequest, true); log.trace("Request URL: " + requestURL); AuthenticationManager authManager = AuthenticationManager.getInstance(); if (!authManager.isActiveUser(authuser) && !this.isExcluded(requestURL)) { if (!this.isExcluded(requestURL)) { //user is not active anymore. Invalidate session and reauthenticate user String authID = (String) session.getAttribute(Constants.SESSION_PVP2REQUESTID); session.invalidate(); authuser = null; //TODO: set infotext session = httpServletRequest.getSession(true); session.setAttribute(Constants.SESSION_PVP2REQUESTID, authID); } if (config.isLoginDeaktivated()) { //add dummy Daten log.warn("Authentication is deaktivated. Dummy authentication-information are used!"); if (authuser == null) { int sessionTimeOut = session.getMaxInactiveInterval(); Date sessionExpired = new Date(new Date().getTime() + (sessionTimeOut * Constants.ONE_MINUTE_IN_MILLIS)); authuser = AuthenticatedUser.generateDefaultUser(sessionExpired); authManager.setActiveUser(authuser); //authuser = new AuthenticatedUser(1, "Max", "TestUser", true, false); httpServletRequest.getSession().setAttribute(Constants.SESSION_AUTH, authuser); } if (MiscUtil.isNotEmpty(getAuthenticatedPage())) { if (loginPageForward) { log.debug("Authenticated page is set. Forwarding to \"" + getAuthenticatedPage() + "\"."); RequestDispatcher dispatcher = req.getRequestDispatcher(getAuthenticatedPage()); dispatcher.forward(httpServletRequest, httpServletResponse); } else { log.debug("Authenticated page is set. Redirecting to \"" + getAuthenticatedPage() + "\"."); httpServletResponse.sendRedirect(httpServletResponse.encodeRedirectURL(getAuthenticatedPage())); } return; } } else { if (MiscUtil.isNotEmpty(getAuthenticatedPage())) { log.debug("Unable to find authentication data. Authenticated page is given so there is no need to save original request url. " + (loginPageForward ? "Forwarding" : "Redirecting") + " to login page \"" + loginPage + "\"."); } else { log.debug("Unable to find authentication data. Storing request url and " + (loginPageForward ? "forwarding" : "redirecting") + " to login page \"" + loginPage + "\"."); session.setAttribute(STORED_REQUEST_URL_ID, requestURL); } if (loginPageForward) { RequestDispatcher dispatcher = req.getRequestDispatcher(loginPage); dispatcher.forward(httpServletRequest, httpServletResponse); return; } else { httpServletResponse.sendRedirect(httpServletResponse.encodeRedirectURL(loginPage)); return; } } } else { try { filterchain.doFilter(req, resp); } catch (Exception e) { log.error("Servlet filter catchs an unhandled exception! Msg: " + e.getMessage(), e); //String redirectURL = "./index.action"; //HttpServletResponse httpResp = (HttpServletResponse) resp; //redirectURL = httpResp.encodeRedirectURL(redirectURL); //resp.setContentType("text/html"); //((HttpServletResponse) resp).setStatus(302); //httpResp.addHeader("Location", redirectURL); //log.warn("A Filter Error occurs -> Redirect to Login-Form"); } } } public void init(FilterConfig filterConfig) throws ServletException { log.debug("Starting init of " + this.getClass().getName() + "."); try { config = ConfigurationProvider.getInstance(); } catch (ConfigurationException e) { throw new ServletException(e.getMessage(), e); } // login page loginPage = StringUtils.trim(filterConfig.getInitParameter(WEB_XML_INIT_PARAM_LOGIN_PAGE)); if (MiscUtil.isEmpty(loginPage)) { throw new ServletException("ServletInitParameter \"" + WEB_XML_INIT_PARAM_LOGIN_PAGE + "\" must not be empty."); } loginPageForward = false; //!WebAppUtil.isFullQualifiedURL(loginPage); // error page errorPage = StringUtils.trim(filterConfig.getInitParameter(WEB_XML_INIT_PARAM_ERROR_PAGE)); if (MiscUtil.isEmpty(errorPage)) { throw new ServletException("ServletInitParameter \"" + WEB_XML_INIT_PARAM_ERROR_PAGE + "\" must not be empty."); } // session lost page sessionLostPage = StringUtils.trim(filterConfig.getInitParameter(WEB_XML_INIT_PARAM_SESSION_LOST_PAGE)); if (MiscUtil.isEmpty(sessionLostPage)) { log.warn("ServletInitParameter \"" + WEB_XML_INIT_PARAM_SESSION_LOST_PAGE + "\" is empty. This parameter defines a failsafe url the browser is redirected to if the original url has been lost due to session timeout."); } // authenticated page authenticatedPage = StringUtils.trim(filterConfig.getInitParameter(WEB_XML_INIT_PARAM_AUTHENTICATED_PAGE)); if (MiscUtil.isEmpty(authenticatedPage)) { log.debug("ServletInitParameter \"" + WEB_XML_INIT_PARAM_AUTHENTICATED_PAGE + "\" is empty. This parameter defines the url the user is redirected to (instead of the original url) on successful authentication."); } String excluded = filterConfig.getInitParameter(WEB_XML_INIT_PARAM_ALLOWED_LIST); ArrayList excludedList = new ArrayList(); if (MiscUtil.isNotEmpty(excluded)) { StringTokenizer tokenizer = new StringTokenizer(excluded, WEB_XML_INIT_PARAM_EXCLUDED_PAGES_DELIMITER); while (tokenizer.hasMoreTokens()) { String ex = StringUtils.trim(tokenizer.nextToken()); if (MiscUtil.isNotEmpty(ex)) { excludedList.add(ex); } } } excludedList.add(loginPage); excludedList.add(errorPage); excludedPages = new String[excludedList.size()]; excludedPages = excludedList.toArray(excludedPages); String excludedRegExString = StringUtils.trim(filterConfig.getInitParameter(WEB_XML_INIT_PARAM_ALLOWED_REGEX)); if (MiscUtil.isNotEmpty(excludedRegExString)) { excludedRegEx = Pattern.compile(excludedRegExString); } log.debug(WEB_XML_INIT_PARAM_LOGIN_PAGE + " [" + (loginPageForward ? "forward" : "redirect") + "] = \"" + loginPage + "\""); log.debug(WEB_XML_INIT_PARAM_AUTHENTICATED_PAGE + " = \"" + (MiscUtil.isNotEmpty(authenticatedPage) ? authenticatedPage : "") + "\""); log.debug(WEB_XML_INIT_PARAM_ERROR_PAGE + " = \"" + errorPage + "\""); log.debug(WEB_XML_INIT_PARAM_SESSION_LOST_PAGE + " = \"" + (MiscUtil.isNotEmpty(sessionLostPage) ? sessionLostPage : "") + "\""); log.debug(WEB_XML_INIT_PARAM_ALLOWED_LIST + " = " + ToStringUtil.toString(excludedPages, ", ", "\"")); log.debug(WEB_XML_INIT_PARAM_ALLOWED_REGEX + " = \"" + (excludedRegEx != null ? excludedRegEx.pattern() : "") + "\""); } }