001/* 002 * Copyright 2002-2017 the original author or authors. 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 * https://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 017package org.springframework.web.socket.server.support; 018 019import java.util.Collection; 020import java.util.Collections; 021import java.util.Enumeration; 022import java.util.Map; 023 024import javax.servlet.http.HttpSession; 025 026import org.springframework.http.server.ServerHttpRequest; 027import org.springframework.http.server.ServerHttpResponse; 028import org.springframework.http.server.ServletServerHttpRequest; 029import org.springframework.lang.Nullable; 030import org.springframework.web.socket.WebSocketHandler; 031import org.springframework.web.socket.WebSocketSession; 032import org.springframework.web.socket.server.HandshakeInterceptor; 033 034/** 035 * An interceptor to copy information from the HTTP session to the "handshake 036 * attributes" map to made available via{@link WebSocketSession#getAttributes()}. 037 * 038 * <p>Copies a subset or all HTTP session attributes and/or the HTTP session id 039 * under the key {@link #HTTP_SESSION_ID_ATTR_NAME}. 040 * 041 * @author Rossen Stoyanchev 042 * @since 4.0 043 */ 044public class HttpSessionHandshakeInterceptor implements HandshakeInterceptor { 045 046 /** 047 * The name of the attribute under which the HTTP session id is exposed when 048 * {@link #setCopyHttpSessionId(boolean) copyHttpSessionId} is "true". 049 */ 050 public static final String HTTP_SESSION_ID_ATTR_NAME = "HTTP.SESSION.ID"; 051 052 053 private final Collection<String> attributeNames; 054 055 private boolean copyAllAttributes; 056 057 private boolean copyHttpSessionId = true; 058 059 private boolean createSession; 060 061 062 /** 063 * Default constructor for copying all HTTP session attributes and the HTTP 064 * session id. 065 * @see #setCopyAllAttributes 066 * @see #setCopyHttpSessionId 067 */ 068 public HttpSessionHandshakeInterceptor() { 069 this.attributeNames = Collections.emptyList(); 070 this.copyAllAttributes = true; 071 } 072 073 /** 074 * Constructor for copying specific HTTP session attributes and the HTTP 075 * session id. 076 * @param attributeNames session attributes to copy 077 * @see #setCopyAllAttributes 078 * @see #setCopyHttpSessionId 079 */ 080 public HttpSessionHandshakeInterceptor(Collection<String> attributeNames) { 081 this.attributeNames = Collections.unmodifiableCollection(attributeNames); 082 this.copyAllAttributes = false; 083 } 084 085 086 /** 087 * Return the configured attribute names to copy (read-only). 088 */ 089 public Collection<String> getAttributeNames() { 090 return this.attributeNames; 091 } 092 093 /** 094 * Whether to copy all attributes from the HTTP session. If set to "true", 095 * any explicitly configured attribute names are ignored. 096 * <p>By default this is set to either "true" or "false" depending on which 097 * constructor was used (default or with attribute names respectively). 098 * @param copyAllAttributes whether to copy all attributes 099 */ 100 public void setCopyAllAttributes(boolean copyAllAttributes) { 101 this.copyAllAttributes = copyAllAttributes; 102 } 103 104 /** 105 * Whether to copy all HTTP session attributes. 106 */ 107 public boolean isCopyAllAttributes() { 108 return this.copyAllAttributes; 109 } 110 111 /** 112 * Whether the HTTP session id should be copied to the handshake attributes 113 * under the key {@link #HTTP_SESSION_ID_ATTR_NAME}. 114 * <p>By default this is "true". 115 * @param copyHttpSessionId whether to copy the HTTP session id. 116 */ 117 public void setCopyHttpSessionId(boolean copyHttpSessionId) { 118 this.copyHttpSessionId = copyHttpSessionId; 119 } 120 121 /** 122 * Whether to copy the HTTP session id to the handshake attributes. 123 */ 124 public boolean isCopyHttpSessionId() { 125 return this.copyHttpSessionId; 126 } 127 128 /** 129 * Whether to allow the HTTP session to be created while accessing it. 130 * <p>By default set to {@code false}. 131 * @see javax.servlet.http.HttpServletRequest#getSession(boolean) 132 */ 133 public void setCreateSession(boolean createSession) { 134 this.createSession = createSession; 135 } 136 137 /** 138 * Whether the HTTP session is allowed to be created. 139 */ 140 public boolean isCreateSession() { 141 return this.createSession; 142 } 143 144 145 @Override 146 public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, 147 WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception { 148 149 HttpSession session = getSession(request); 150 if (session != null) { 151 if (isCopyHttpSessionId()) { 152 attributes.put(HTTP_SESSION_ID_ATTR_NAME, session.getId()); 153 } 154 Enumeration<String> names = session.getAttributeNames(); 155 while (names.hasMoreElements()) { 156 String name = names.nextElement(); 157 if (isCopyAllAttributes() || getAttributeNames().contains(name)) { 158 attributes.put(name, session.getAttribute(name)); 159 } 160 } 161 } 162 return true; 163 } 164 165 @Nullable 166 private HttpSession getSession(ServerHttpRequest request) { 167 if (request instanceof ServletServerHttpRequest) { 168 ServletServerHttpRequest serverRequest = (ServletServerHttpRequest) request; 169 return serverRequest.getServletRequest().getSession(isCreateSession()); 170 } 171 return null; 172 } 173 174 @Override 175 public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, 176 WebSocketHandler wsHandler, @Nullable Exception ex) { 177 } 178 179}