/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.synapse.endpoints.dispatch; import org.apache.http.protocol.HTTP; import org.apache.synapse.MessageContext; import org.apache.synapse.core.axis2.Axis2MessageContext; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * Dispatches sessions based on HTTP cookies. Session is initiated by the server in the first * response when it sends "Set-Cookie" HTTP header with the session ID. For all successive messages * client should send "Cookie" HTTP header with session ID send by the server. */ public class HttpSessionDispatcher extends AbstractDispatcher { /*HTTP Headers */ private final static String COOKIE = "Cookie"; private final static String SET_COOKIE = "Set-Cookie"; public static final String HOSTS = "hosts"; /** * Check if "Cookie" HTTP header is available. If so, check if that cookie is in the session * map. If cookie is available, there is a session for this cookie. return the (server) * endpoint for that session. * * @param synCtx MessageContext possibly containing a "Cookie" HTTP header. * @return Endpoint Server endpoint for the given HTTP session. */ public SessionInformation getSession(MessageContext synCtx) { String hostName = extractHost(synCtx); if (log.isDebugEnabled()) { log.debug("Extracted Host Name : " + hostName); } // print TO org.apache.axis2.context.MessageContext axis2MessageContext = ((Axis2MessageContext) synCtx).getAxis2MessageContext(); if (log.isDebugEnabled()) { log.debug("Endpoint Address : " + axis2MessageContext.getTo().getAddress()); } Map headerMap = getTransportHeaderMap(synCtx); String contentType = (String)headerMap.get("Content-Type"); if (log.isDebugEnabled()) { log.debug("Content Type : " + contentType); } if (hostName == null) { return SALSessions.getInstance().getSession(extractSessionID(synCtx, COOKIE)); } else { List<String> sessionList = extractSessionIDs(synCtx, COOKIE); if (sessionList != null) { for (String sessionID : sessionList) { SessionInformation sessionInfoObj = SALSessions.getInstance().getSession(sessionID); if (sessionInfoObj != null && sessionInfoObj.getMember() != null) { Map<String, String> subDomainNames = (Map<String, String>) sessionInfoObj.getMember().getProperties().get(HOSTS); if (log.isDebugEnabled()) { log.debug("Member Domain : " + (subDomainNames != null ? subDomainNames.get(hostName) : null) + " : Session ID " + sessionID); } if (subDomainNames != null && subDomainNames.get(hostName) != null) { if (log.isDebugEnabled()) { log.debug("Found a matching sessionInfo Object for the " + hostName); } return sessionInfoObj; } } else if (sessionInfoObj != null && sessionInfoObj.getMember() == null) { // looks like a session attached to a failed member.Just return the session in this case if (log.isDebugEnabled()) { log.debug("sessionInfo object[" + sessionInfoObj.getId()+ "] found with a null member. " + "Looks like this is attached to a failed member."); } return sessionInfoObj; } } } } if (log.isDebugEnabled()) { log.debug("Did not find a session info obj."); } return null; } /** * Searches for "Set-Cookie" HTTP header in the message context. If found and that given * session ID is not already in the session map update the session map by mapping the cookie * to the endpoint. * * @param synCtx MessageContext possibly containing the "Set-Cookie" HTTP header. */ public void updateSession(MessageContext synCtx) { SessionCookie cookie = extractSessionCookie(synCtx, SET_COOKIE); if (cookie != null) { if (log.isDebugEnabled()) { log.debug("Found the HTTP header [Set-Cookie]: " + cookie.toString() + "' for updating the session"); } SALSessions.getInstance().updateSession(synCtx, cookie); } } public void unbind(MessageContext synCtx) { SALSessions.getInstance().removeSession(extractSessionID(synCtx, COOKIE)); } /** * HTTP sessions are initiated by the server. * * @return true */ public boolean isServerInitiatedSession() { return true; } public void removeSessionID(MessageContext syCtx) { removeSessionID(syCtx, COOKIE); } protected List<String> extractSessionIDs(MessageContext synCtx, String key) { List<String> sessionList = new ArrayList<String>(); if (key != null) { Map headerMap = getTransportHeaderMap(synCtx); if (headerMap != null) { Object hostObj = headerMap.get("Host"); if (log.isDebugEnabled()) { log.debug("A request received with the Host Name : " + (String) hostObj); } Object cookieObj = headerMap.get(key); if (cookieObj instanceof String) { String cookie = (String) cookieObj; if (log.isDebugEnabled()) { log.debug("Cookies String : " + cookie); } // extract the first name value pair of the Set-Cookie header, which is considered // as the session id which will be sent back from the client with the Cookie header // for example; // Set-Cookie: JSESSIONID=760764CB72E96A7221506823748CF2AE; Path=/ // will result in the session id "JSESSIONID=760764CB72E96A7221506823748CF2AE" String[] sessionIds = cookie.split(";"); if (sessionIds == null || sessionIds.length == 0) { if (log.isDebugEnabled()) { log.debug("Cannot find a session id for the cookie : " + cookie); } return null; } for(String sessionId : sessionIds){ if (sessionId != null && (sessionId.indexOf("JSESSIONID") != -1 || sessionId .indexOf("PHPSESSID") != -1 || sessionId.indexOf("phpMyAdmin") != -1 || sessionId.indexOf("wordpress_test_cookie") != -1)) { if (log.isDebugEnabled()) { log.debug("Extracted SessionID : " + sessionId); } sessionList.add(sessionId.trim()); } } } else { if (log.isDebugEnabled()) { log.debug("Couldn't find the " + key + " header to find the session"); } } } else { if (log.isDebugEnabled()) { log.debug("Couldn't find the TRANSPORT_HEADERS to find the session"); } } } return sessionList; } private String extractHost(MessageContext synCtx) { Map headerMap = getTransportHeaderMap(synCtx); String hostName = null; if (headerMap != null) { Object hostObj = headerMap.get(HTTP.TARGET_HOST); hostName = (String) hostObj; if (hostName != null && hostName.contains(":")) { hostName = hostName.substring(0, hostName.indexOf(":")); } } return hostName; } private Map getTransportHeaderMap(MessageContext synCtx) { org.apache.axis2.context.MessageContext axis2MessageContext = ((Axis2MessageContext) synCtx).getAxis2MessageContext(); Object o = axis2MessageContext.getProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS); if (o != null && o instanceof Map) { return (Map) o; } return null; } }