001/* 002 * (C) Copyright 2012 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * bjalon 018 */ 019package org.nuxeo.ecm.mobile.filter; 020 021import java.io.IOException; 022import java.util.HashMap; 023import java.util.Map; 024 025import javax.servlet.Filter; 026import javax.servlet.FilterChain; 027import javax.servlet.FilterConfig; 028import javax.servlet.ServletException; 029import javax.servlet.ServletRequest; 030import javax.servlet.ServletResponse; 031import javax.servlet.http.HttpServletRequest; 032import javax.servlet.http.HttpServletResponse; 033 034import org.apache.commons.lang.StringUtils; 035import org.apache.commons.logging.Log; 036import org.apache.commons.logging.LogFactory; 037import org.nuxeo.common.utils.URIUtils; 038import org.nuxeo.ecm.mobile.ApplicationDefinitionService; 039import org.nuxeo.ecm.platform.ui.web.auth.CachableUserIdentificationInfo; 040import org.nuxeo.ecm.platform.ui.web.auth.NuxeoAuthenticationFilter; 041import org.nuxeo.runtime.api.Framework; 042 043/** 044 * Filter that redirects to the chosen application URL or application dedicated for the context request. 045 * To understand the application selection engine look {@code ApplicationDefinitionService#getTargetApplication(HttpServletRequest). 046 * If no application match, no redirection will be executed. 047 * 048 * @author <a href="mailto:bjalon@nuxeo.com">Benjamin JALON</a> 049 * @since 5.5 050 * 051 */ 052public class ApplicationRedirectionFilter implements Filter { 053 054 protected static final Log log = LogFactory.getLog(ApplicationRedirectionFilter.class); 055 056 public static final String INITIAL_TARGET_URL_PARAM_NAME = "targetURL"; 057 058 private ApplicationDefinitionService service; 059 060 protected ApplicationDefinitionService getService() { 061 if (service == null) { 062 service = Framework.getLocalService(ApplicationDefinitionService.class); 063 } 064 return service; 065 } 066 067 @Override 068 public void init(FilterConfig filterConfig) throws ServletException { 069 // Nothing to do 070 } 071 072 @Override 073 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, 074 ServletException { 075 if (!(request instanceof HttpServletRequest)) { 076 log.debug("Not an Http request, no redirection"); 077 doNoRedirect(request, response, chain); 078 return; 079 } 080 081 HttpServletRequest req = (HttpServletRequest) request; 082 log.debug("do filter - URL :" + req.getRequestURL() + "?" + req.getQueryString()); 083 084 if (!isAuthenticated(req)) { 085 log.debug("User not authenticated so no application redirection"); 086 doNoRedirect(request, response, chain); 087 return; 088 } 089 090 String targetApplicationBaseURL = getService().getApplicationBaseURI(req); 091 092 if (targetApplicationBaseURL == null) { 093 log.debug("No application match this request context " + "=> no redirect: final URL: " 094 + req.getRequestURI()); 095 doNoRedirect(request, response, chain); 096 return; 097 } 098 099 if (isRequestIntoApplication(req, targetApplicationBaseURL)) { 100 log.debug("Request URI is a child of target application so no redirect:" + " final URL: " 101 + req.getRequestURI()); 102 doNoRedirect(request, response, chain); 103 return; 104 } 105 106 if (getService().isResourceURL(req)) { 107 log.debug("Request URI is a resource of the target application so no redirect:" + " final URL: " 108 + req.getRequestURI()); 109 doNoRedirect(request, response, chain); 110 return; 111 } 112 113 RequestAdapter requestAdapter = new RequestAdapter(req); 114 if (requestAdapter.isOpenURL()) { 115 log.debug("Request URI is opened so no redirect:" + " final URL: " + req.getRequestURI()); 116 doNoRedirect(request, response, chain); 117 return; 118 } 119 120 doApplicationRedirection((HttpServletRequest) request, (HttpServletResponse) response, chain); 121 } 122 123 /** 124 * Return principal stored into session 125 */ 126 private boolean isAuthenticated(HttpServletRequest req) { 127 if (req.getSession(false) == null) { 128 return false; 129 } 130 131 CachableUserIdentificationInfo idInfo = (CachableUserIdentificationInfo) req.getSession().getAttribute( 132 "org.nuxeo.ecm.login.identity"); 133 134 if (idInfo == null || idInfo.getPrincipal() == null) { 135 return false; 136 } 137 138 return true; 139 } 140 141 /** 142 * Redirect the browser to the target application with the initial URL as parameter into the 143 * {@value WebMobileConstants#TARGET_URL_PARAMETER} url parameter. 144 */ 145 private void doApplicationRedirection(HttpServletRequest request, HttpServletResponse response, FilterChain chain) 146 throws IOException, ServletException { 147 Map<String, String> parameters = new HashMap<String, String>(); 148 149 String requestedPage = NuxeoAuthenticationFilter.getRequestedPage(request); 150 if (!StringUtils.isBlank(requestedPage)) { 151 parameters.put(INITIAL_TARGET_URL_PARAM_NAME, requestedPage); 152 } 153 154 String redirectURI = URIUtils.addParametersToURIQuery(getService().getApplicationBaseURL(request), parameters); 155 log.debug("Handler match/Non target application URI " + "=> Application redirected: target URL: " + redirectURI); 156 157 response.sendRedirect(redirectURI); 158 } 159 160 /** 161 * Do no redirection and let filters application to be done. 162 */ 163 private void doNoRedirect(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, 164 ServletException { 165 chain.doFilter(request, response); 166 } 167 168 private boolean isRequestIntoApplication(HttpServletRequest req, String targetApplicationBaseURL) { 169 String uri = req.getRequestURI(); 170 171 log.debug("Request url: " + uri + " and targetApplicationURI: "); 172 if (!uri.startsWith(targetApplicationBaseURL)) { 173 log.debug("Request uri is not a child of application base url"); 174 return false; 175 } 176 if (uri.equals(targetApplicationBaseURL)) { 177 log.debug("Request uri is the root of the application"); 178 return true; 179 } 180 char character = uri.charAt(targetApplicationBaseURL.length()); 181 if (character != '/' && character != '?' && character != '#' && character != '@') { 182 log.debug("Request uri is not a child of application base url"); 183 return false; 184 } 185 log.debug("Request uri is a child of application base url"); 186 return true; 187 } 188 189 @Override 190 public void destroy() { 191 log.debug("Filter detroyed"); 192 } 193 194}