001/* 002 * Copyright 2016 Anyware Services 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 */ 016package org.ametys.web; 017 018import java.util.ArrayList; 019import java.util.Collection; 020import java.util.List; 021import java.util.Map; 022 023import org.apache.avalon.framework.parameters.Parameters; 024import org.apache.avalon.framework.service.ServiceException; 025import org.apache.avalon.framework.service.ServiceManager; 026import org.apache.cocoon.environment.ObjectModelHelper; 027import org.apache.cocoon.environment.Redirector; 028import org.apache.cocoon.environment.Request; 029import org.apache.cocoon.environment.SourceResolver; 030import org.apache.commons.collections.CollectionUtils; 031 032import org.ametys.core.authentication.AuthenticateAction; 033import org.ametys.core.user.UserIdentity; 034import org.ametys.core.util.StringUtils; 035import org.ametys.runtime.authentication.AccessDeniedException; 036import org.ametys.runtime.config.Config; 037import org.ametys.web.repository.site.SiteManager; 038 039/** 040 * Special authentication process for web context and aware of front-offices. 041 */ 042public class WebAuthenticateAction extends AuthenticateAction 043{ 044 /** The request attribute to set front office user identity */ 045 public static final String REQUEST_ATTRIBUTE_FRONTOFFICE_USERIDENTITY = "Web:FrontOffice:UserIdentity"; 046 /** The request attribute set to "true" when the request came from the front and was IP checked */ 047 public static final String REQUEST_ATTRIBUTE_FRONTOFFICE_REQUEST = "Web:FrontOffice:Request"; 048 049 private SiteManager _siteManager; 050 051 @Override 052 public void service(ServiceManager smanager) throws ServiceException 053 { 054 _siteManager = (SiteManager) smanager.lookup(SiteManager.ROLE); 055 super.service(smanager); 056 } 057 058 @Override 059 protected List<String> _getContexts(Request request, Parameters parameters) 060 { 061 // We return all the populations linked to at least one site 062 List<String> contexts = new ArrayList<>(); 063 064 // Retrieve the sites to build the contexts to search on 065 Collection<String> siteNames = _siteManager.getSiteNames(); 066 067 for (String context : super._getContexts(request, parameters)) 068 { 069 for (String siteName : siteNames) 070 { 071 String siteContext = context + "/" + siteName; 072 contexts.add(siteContext); 073 } 074 } 075 076 return contexts; 077 } 078 079 @Override 080 public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception 081 { 082 Request request = ObjectModelHelper.getRequest(objectModel); 083 if ("true".equals(request.getHeader("X-Ametys-FO"))) 084 { 085 // The request seems to come from an FO, verify the IP address 086 String conf = Config.getInstance().getValue("org.ametys.web.front.ip"); 087 Collection<String> ips = StringUtils.stringToCollection(conf); 088 089 // The real client IP may have been put in the non-standard "X-Forwarded-For" request header, in case of reverse proxy 090 String xff = request.getHeader("X-Forwarded-For"); 091 Collection<String> remoteIps = StringUtils.stringToCollection(xff); 092 remoteIps.add(request.getRemoteAddr()); 093 094 if (!ips.isEmpty() && !CollectionUtils.containsAny(ips, remoteIps)) 095 { 096 throw new AccessDeniedException("IP '" + org.apache.commons.lang.StringUtils.join(remoteIps, ", ") + "' is not an authorized front-office IP (" + conf + ")"); 097 } 098 099 String login = request.getHeader("X-Ametys-FO-Login"); 100 String populationId = request.getHeader("X-Ametys-FO-Population"); 101 if (org.apache.commons.lang3.StringUtils.isNoneBlank(login, populationId)) 102 { 103 UserIdentity frontUserIdentity = new UserIdentity(login, populationId); 104 request.setAttribute(REQUEST_ATTRIBUTE_FRONTOFFICE_USERIDENTITY, frontUserIdentity); 105 } 106 107 request.setAttribute(REQUEST_ATTRIBUTE_AUTHENTICATED, "true"); 108 request.setAttribute(REQUEST_ATTRIBUTE_FRONTOFFICE_REQUEST, "true"); 109 return EMPTY_MAP; 110 } 111 112 request.setAttribute(REQUEST_ATTRIBUTE_FRONTOFFICE_REQUEST, "false"); // A request using the dispatch generator can add anything in the request attributes 113 return super.act(redirector, resolver, objectModel, source, parameters); 114 } 115}