|
15 | 15 | */
|
16 | 16 | package org.springframework.web.server.session;
|
17 | 17 |
|
18 |
| -import java.time.Clock; |
19 |
| -import java.time.Instant; |
20 |
| -import java.time.ZoneId; |
21 | 18 | import java.util.List;
|
22 | 19 |
|
23 | 20 | import reactor.core.publisher.Flux;
|
24 | 21 | import reactor.core.publisher.Mono;
|
25 | 22 |
|
26 | 23 | import org.springframework.util.Assert;
|
27 |
| -import org.springframework.util.IdGenerator; |
28 |
| -import org.springframework.util.JdkIdGenerator; |
29 | 24 | import org.springframework.web.server.ServerWebExchange;
|
30 | 25 | import org.springframework.web.server.WebSession;
|
31 | 26 |
|
|
36 | 31 | * {@link WebSessionStore}
|
37 | 32 | *
|
38 | 33 | * @author Rossen Stoyanchev
|
| 34 | + * @author Rob Winch |
39 | 35 | * @since 5.0
|
40 | 36 | */
|
41 | 37 | public class DefaultWebSessionManager implements WebSessionManager {
|
42 | 38 |
|
43 |
| - private static final IdGenerator idGenerator = new JdkIdGenerator(); |
44 |
| - |
45 |
| - |
46 | 39 | private WebSessionIdResolver sessionIdResolver = new CookieWebSessionIdResolver();
|
47 | 40 |
|
48 | 41 | private WebSessionStore sessionStore = new InMemoryWebSessionStore();
|
49 | 42 |
|
50 |
| - private Clock clock = Clock.system(ZoneId.of("GMT")); |
51 |
| - |
52 | 43 |
|
53 | 44 | /**
|
54 | 45 | * Configure the id resolution strategy.
|
@@ -84,89 +75,53 @@ public WebSessionStore getSessionStore() {
|
84 | 75 | return this.sessionStore;
|
85 | 76 | }
|
86 | 77 |
|
87 |
| - /** |
88 |
| - * Configure the {@link Clock} to use to set lastAccessTime on every created |
89 |
| - * session and to calculate if it is expired. |
90 |
| - * <p>This may be useful to align to different timezone or to set the clock |
91 |
| - * back in a test, e.g. {@code Clock.offset(clock, Duration.ofMinutes(-31))} |
92 |
| - * in order to simulate session expiration. |
93 |
| - * <p>By default this is {@code Clock.system(ZoneId.of("GMT"))}. |
94 |
| - * @param clock the clock to use |
95 |
| - */ |
96 |
| - public void setClock(Clock clock) { |
97 |
| - Assert.notNull(clock, "'clock' is required."); |
98 |
| - this.clock = clock; |
99 |
| - } |
100 |
| - |
101 |
| - /** |
102 |
| - * Return the configured clock for session lastAccessTime calculations. |
103 |
| - */ |
104 |
| - public Clock getClock() { |
105 |
| - return this.clock; |
106 |
| - } |
107 |
| - |
108 | 78 |
|
109 | 79 | @Override
|
110 | 80 | public Mono<WebSession> getSession(ServerWebExchange exchange) {
|
111 | 81 | return Mono.defer(() ->
|
112 | 82 | retrieveSession(exchange)
|
113 | 83 | .flatMap(session -> removeSessionIfExpired(exchange, session))
|
114 |
| - .map(session -> { |
115 |
| - Instant lastAccessTime = Instant.now(getClock()); |
116 |
| - return new DefaultWebSession(session, lastAccessTime, s -> saveSession(exchange, s)); |
117 |
| - }) |
118 |
| - .switchIfEmpty(createSession(exchange)) |
119 |
| - .doOnNext(session -> exchange.getResponse().beforeCommit(session::save))); |
| 84 | + .flatMap(this.getSessionStore()::updateLastAccessTime) |
| 85 | + .switchIfEmpty(this.sessionStore.createWebSession()) |
| 86 | + .doOnNext(session -> exchange.getResponse().beforeCommit(() -> save(exchange, session)))); |
120 | 87 | }
|
121 | 88 |
|
122 |
| - private Mono<DefaultWebSession> retrieveSession(ServerWebExchange exchange) { |
| 89 | + private Mono<WebSession> retrieveSession(ServerWebExchange exchange) { |
123 | 90 | return Flux.fromIterable(getSessionIdResolver().resolveSessionIds(exchange))
|
124 | 91 | .concatMap(this.sessionStore::retrieveSession)
|
125 |
| - .cast(DefaultWebSession.class) |
126 | 92 | .next();
|
127 | 93 | }
|
128 | 94 |
|
129 |
| - private Mono<DefaultWebSession> removeSessionIfExpired(ServerWebExchange exchange, DefaultWebSession session) { |
| 95 | + private Mono<WebSession> removeSessionIfExpired(ServerWebExchange exchange, WebSession session) { |
130 | 96 | if (session.isExpired()) {
|
131 | 97 | this.sessionIdResolver.expireSession(exchange);
|
132 | 98 | return this.sessionStore.removeSession(session.getId()).then(Mono.empty());
|
133 | 99 | }
|
134 | 100 | return Mono.just(session);
|
135 | 101 | }
|
136 | 102 |
|
137 |
| - private Mono<Void> saveSession(ServerWebExchange exchange, WebSession session) { |
| 103 | + private Mono<Void> save(ServerWebExchange exchange, WebSession session) { |
138 | 104 | if (session.isExpired()) {
|
139 | 105 | return Mono.error(new IllegalStateException(
|
140 | 106 | "Sessions are checked for expiration and have their " +
|
141 |
| - "lastAccessTime updated when first accessed during request processing. " + |
142 |
| - "However this session is expired meaning that maxIdleTime elapsed " + |
143 |
| - "before the call to session.save().")); |
| 107 | + "lastAccessTime updated when first accessed during request processing. " + |
| 108 | + "However this session is expired meaning that maxIdleTime elapsed " + |
| 109 | + "before the call to session.save().")); |
144 | 110 | }
|
145 | 111 |
|
146 | 112 | if (!session.isStarted()) {
|
147 | 113 | return Mono.empty();
|
148 | 114 | }
|
149 | 115 |
|
150 |
| - // Force explicit start |
151 |
| - session.start(); |
152 |
| - |
153 | 116 | if (hasNewSessionId(exchange, session)) {
|
154 |
| - this.sessionIdResolver.setSessionId(exchange, session.getId()); |
| 117 | + DefaultWebSessionManager.this.sessionIdResolver.setSessionId(exchange, session.getId()); |
155 | 118 | }
|
156 | 119 |
|
157 |
| - return this.sessionStore.storeSession(session); |
| 120 | + return session.save(); |
158 | 121 | }
|
159 | 122 |
|
160 | 123 | private boolean hasNewSessionId(ServerWebExchange exchange, WebSession session) {
|
161 | 124 | List<String> ids = getSessionIdResolver().resolveSessionIds(exchange);
|
162 | 125 | return ids.isEmpty() || !session.getId().equals(ids.get(0));
|
163 | 126 | }
|
164 |
| - |
165 |
| - private Mono<DefaultWebSession> createSession(ServerWebExchange exchange) { |
166 |
| - return Mono.fromSupplier(() -> |
167 |
| - new DefaultWebSession(idGenerator, getClock(), |
168 |
| - (oldId, session) -> this.sessionStore.changeSessionId(oldId, session), |
169 |
| - session -> saveSession(exchange, session))); |
170 |
| - } |
171 |
| - |
172 | 127 | }
|
0 commit comments