001/* 002 * Copyright 2002-2018 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.server; 018 019import java.time.Duration; 020import java.time.Instant; 021import java.util.Map; 022 023import reactor.core.publisher.Mono; 024 025import org.springframework.lang.Nullable; 026import org.springframework.util.Assert; 027 028/** 029 * Main contract for using a server-side session that provides access to session 030 * attributes across HTTP requests. 031 * 032 * <p>The creation of a {@code WebSession} instance does not automatically start 033 * a session thus causing the session id to be sent to the client (typically via 034 * a cookie). A session starts implicitly when session attributes are added. 035 * A session may also be created explicitly via {@link #start()}. 036 * 037 * @author Rossen Stoyanchev 038 * @since 5.0 039 */ 040public interface WebSession { 041 042 /** 043 * Return a unique session identifier. 044 */ 045 String getId(); 046 047 /** 048 * Return a map that holds session attributes. 049 */ 050 Map<String, Object> getAttributes(); 051 052 /** 053 * Return the session attribute value if present. 054 * @param name the attribute name 055 * @param <T> the attribute type 056 * @return the attribute value 057 */ 058 @SuppressWarnings("unchecked") 059 @Nullable 060 default <T> T getAttribute(String name) { 061 return (T) getAttributes().get(name); 062 } 063 064 /** 065 * Return the session attribute value or if not present raise an 066 * {@link IllegalArgumentException}. 067 * @param name the attribute name 068 * @param <T> the attribute type 069 * @return the attribute value 070 */ 071 @SuppressWarnings("unchecked") 072 default <T> T getRequiredAttribute(String name) { 073 T value = getAttribute(name); 074 Assert.notNull(value, () -> "Required attribute '" + name + "' is missing."); 075 return value; 076 } 077 078 /** 079 * Return the session attribute value, or a default, fallback value. 080 * @param name the attribute name 081 * @param defaultValue a default value to return instead 082 * @param <T> the attribute type 083 * @return the attribute value 084 */ 085 @SuppressWarnings("unchecked") 086 default <T> T getAttributeOrDefault(String name, T defaultValue) { 087 return (T) getAttributes().getOrDefault(name, defaultValue); 088 } 089 090 /** 091 * Force the creation of a session causing the session id to be sent when 092 * {@link #save()} is called. 093 */ 094 void start(); 095 096 /** 097 * Whether a session with the client has been started explicitly via 098 * {@link #start()} or implicitly by adding session attributes. 099 * If "false" then the session id is not sent to the client and the 100 * {@link #save()} method is essentially a no-op. 101 */ 102 boolean isStarted(); 103 104 /** 105 * Generate a new id for the session and update the underlying session 106 * storage to reflect the new id. After a successful call {@link #getId()} 107 * reflects the new session id. 108 * @return completion notification (success or error) 109 */ 110 Mono<Void> changeSessionId(); 111 112 /** 113 * Invalidate the current session and clear session storage. 114 * @return completion notification (success or error) 115 */ 116 Mono<Void> invalidate(); 117 118 /** 119 * Save the session through the {@code WebSessionStore} as follows: 120 * <ul> 121 * <li>If the session is new (i.e. created but never persisted), it must have 122 * been started explicitly via {@link #start()} or implicitly by adding 123 * attributes, or otherwise this method should have no effect. 124 * <li>If the session was retrieved through the {@code WebSessionStore}, 125 * the implementation for this method must check whether the session was 126 * {@link #invalidate() invalidated} and if so return an error. 127 * </ul> 128 * <p>Note that this method is not intended for direct use by applications. 129 * Instead it is automatically invoked just before the response is 130 * committed. 131 * @return {@code Mono} to indicate completion with success or error 132 */ 133 Mono<Void> save(); 134 135 /** 136 * Return {@code true} if the session expired after {@link #getMaxIdleTime() 137 * maxIdleTime} elapsed. 138 * <p>Typically expiration checks should be automatically made when a session 139 * is accessed, a new {@code WebSession} instance created if necessary, at 140 * the start of request processing so that applications don't have to worry 141 * about expired session by default. 142 */ 143 boolean isExpired(); 144 145 /** 146 * Return the time when the session was created. 147 */ 148 Instant getCreationTime(); 149 150 /** 151 * Return the last time of session access as a result of user activity such 152 * as an HTTP request. Together with {@link #getMaxIdleTime() 153 * maxIdleTimeInSeconds} this helps to determine when a session is 154 * {@link #isExpired() expired}. 155 */ 156 Instant getLastAccessTime(); 157 158 /** 159 * Configure the max amount of time that may elapse after the 160 * {@link #getLastAccessTime() lastAccessTime} before a session is considered 161 * expired. A negative value indicates the session should not expire. 162 */ 163 void setMaxIdleTime(Duration maxIdleTime); 164 165 /** 166 * Return the maximum time after the {@link #getLastAccessTime() 167 * lastAccessTime} before a session expires. A negative time indicates the 168 * session doesn't expire. 169 */ 170 Duration getMaxIdleTime(); 171 172}