forked from spring-projects-experimental/spring-fu
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add initial reactive redis session support
Relates to spring-projects-experimental#263
- Loading branch information
Showing
10 changed files
with
457 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
45 changes: 45 additions & 0 deletions
45
...ingframework/boot/autoconfigure/session/RedisReactiveSessionConfigurationInitializer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package org.springframework.boot.autoconfigure.session; | ||
|
||
import org.springframework.boot.autoconfigure.session.RedisReactiveSessionConfiguration.SpringBootRedisWebSessionConfiguration; | ||
import org.springframework.context.ApplicationContextInitializer; | ||
import org.springframework.context.support.GenericApplicationContext; | ||
import org.springframework.core.ResolvableType; | ||
import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory; | ||
import org.springframework.data.redis.serializer.RedisSerializer; | ||
import org.springframework.session.ReactiveSessionRepository; | ||
import org.springframework.session.config.ReactiveSessionRepositoryCustomizer; | ||
import org.springframework.session.data.redis.ReactiveRedisSessionRepository; | ||
|
||
/** | ||
* {@link ApplicationContextInitializer} adapter for {@link RedisReactiveSessionConfiguration}. | ||
*/ | ||
public class RedisReactiveSessionConfigurationInitializer { | ||
|
||
private final SessionProperties sessionProperties; | ||
private final RedisSessionProperties redisSessionProperties; | ||
|
||
public RedisReactiveSessionConfigurationInitializer(SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties) { | ||
this.sessionProperties = sessionProperties; | ||
this.redisSessionProperties = redisSessionProperties; | ||
} | ||
|
||
public void initialize(GenericApplicationContext context) { | ||
SpringBootRedisWebSessionConfiguration springBootRedisWebSessionConfiguration = new SpringBootRedisWebSessionConfiguration(); | ||
|
||
springBootRedisWebSessionConfiguration.customize(sessionProperties, redisSessionProperties); | ||
|
||
context.registerBean(ReactiveSessionRepository.class, () -> { | ||
springBootRedisWebSessionConfiguration.setRedisConnectionFactory( | ||
context.getBeanProvider(ReactiveRedisConnectionFactory.class), // TODO use @SpringSessionRedisConnectionFactory annotation qualifier | ||
context.getBeanProvider(ReactiveRedisConnectionFactory.class) | ||
); | ||
springBootRedisWebSessionConfiguration.setDefaultRedisSerializer( | ||
(RedisSerializer<Object>) context.getBeanProvider(ResolvableType.forClassWithGenerics(RedisSerializer.class, Object.class)).getIfAvailable() | ||
); | ||
springBootRedisWebSessionConfiguration.setSessionRepositoryCustomizer( | ||
context.getBeanProvider(ResolvableType.forClassWithGenerics(ReactiveSessionRepositoryCustomizer.class, ReactiveRedisSessionRepository.class)) | ||
); | ||
return springBootRedisWebSessionConfiguration.sessionRepository(); | ||
}); | ||
} | ||
} |
36 changes: 36 additions & 0 deletions
36
...pter/src/main/java/org/springframework/boot/autoconfigure/session/SessionInitializer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package org.springframework.boot.autoconfigure.session; | ||
|
||
import org.springframework.context.ApplicationContextInitializer; | ||
import org.springframework.context.support.GenericApplicationContext; | ||
import org.springframework.core.ResolvableType; | ||
import org.springframework.session.ReactiveSessionRepository; | ||
import org.springframework.session.Session; | ||
import org.springframework.session.config.annotation.web.server.EnableSpringWebSession; | ||
import org.springframework.session.config.annotation.web.server.SpringWebSessionConfiguration; | ||
import org.springframework.web.server.adapter.WebHttpHandlerBuilder; | ||
import org.springframework.web.server.session.DefaultWebSessionManager; | ||
import org.springframework.web.server.session.WebSessionIdResolver; | ||
import org.springframework.web.server.session.WebSessionManager; | ||
|
||
/** | ||
* {@link ApplicationContextInitializer} adapter for {@link SessionAutoConfiguration} and | ||
* {@link EnableSpringWebSession}. | ||
*/ | ||
public class SessionInitializer { | ||
public void initialize(GenericApplicationContext context) { | ||
// SpringWebSessionConfiguration | ||
context.registerBean(WebHttpHandlerBuilder.WEB_SESSION_MANAGER_BEAN_NAME, WebSessionManager.class, () -> { | ||
SpringWebSessionConfiguration springWebSessionConfiguration = new SpringWebSessionConfiguration(); | ||
WebSessionManager webSessionManager = springWebSessionConfiguration.webSessionManager( | ||
(ReactiveSessionRepository<? extends Session>) context.getBeanProvider( | ||
ResolvableType.forClassWithGenerics(ReactiveSessionRepository.class, Session.class) | ||
).getIfAvailable() | ||
); | ||
WebSessionIdResolver webSessionIdResolver = context.getBeanProvider(WebSessionIdResolver.class).getIfAvailable(); | ||
if (webSessionIdResolver != null) { | ||
((DefaultWebSessionManager)webSessionManager).setSessionIdResolver(webSessionIdResolver); | ||
} | ||
return webSessionManager; | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
98 changes: 98 additions & 0 deletions
98
kofu/src/main/kotlin/org/springframework/fu/kofu/session/SessionDsl.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
package org.springframework.fu.kofu.session | ||
|
||
import org.springframework.boot.autoconfigure.session.RedisReactiveSessionConfigurationInitializer | ||
import org.springframework.boot.autoconfigure.session.RedisSessionProperties | ||
import org.springframework.boot.autoconfigure.session.SessionInitializer | ||
import org.springframework.boot.autoconfigure.session.SessionProperties | ||
import org.springframework.context.support.GenericApplicationContext | ||
import org.springframework.fu.kofu.AbstractDsl | ||
import org.springframework.fu.kofu.ConfigurationDsl | ||
import org.springframework.session.SaveMode | ||
import java.time.Duration | ||
|
||
/** | ||
* Kofu DSL for spring-session. | ||
* | ||
* Configure spring-session. | ||
* | ||
* Required dependencies can be retrieve using `org.springframework.boot:spring-boot-starter-session`. | ||
* | ||
* @author Ivan Skachkov | ||
*/ | ||
class SessionDsl(private val init: SessionDsl.() -> Unit) : ConfigurationDsl({}) { | ||
|
||
override fun initialize(context: GenericApplicationContext) { | ||
super.initialize(context) | ||
init() | ||
SessionInitializer().initialize(context) | ||
} | ||
} | ||
|
||
/** | ||
* Configure spring-session. | ||
* | ||
* Requires `org.springframework.boot:spring-boot-starter-session` dependency. | ||
* | ||
* @sample org.springframework.fu.kofu.samples.sessionDsl | ||
* @author Ivan Skachkov | ||
*/ | ||
fun ConfigurationDsl.session(dsl: SessionDsl.() -> Unit = {}) { | ||
SessionDsl(dsl).initialize(context) | ||
} | ||
|
||
/** | ||
* Kofu DSL for spring-session-data-redis. | ||
* | ||
* Configure spring-session-data-redis. | ||
* | ||
* Required dependencies can be retrieve using `org.springframework.session:spring-session-data-redis`. | ||
* | ||
* @see SessionProperties, RedisSessionProperties, org.springframework.session.data.redis.config.annotation.web.server.EnableRedisWebSession | ||
* @author Ivan Skachkov | ||
*/ | ||
class ReactiveRedisDsl( | ||
private val init: ReactiveRedisDsl.() -> Unit, | ||
private val sessionProperties: SessionProperties, | ||
private val redisSessionProperties: RedisSessionProperties | ||
) : AbstractDsl() { | ||
|
||
var maxInactiveIntervalInSeconds: Duration | ||
get() = sessionProperties.timeout | ||
set(value) { | ||
sessionProperties.timeout = value | ||
} | ||
|
||
/** | ||
* Namespace for keys used to store sessions. | ||
*/ | ||
var redisNamespace: String | ||
get() = redisSessionProperties.namespace | ||
set(value) { | ||
redisSessionProperties.namespace = value | ||
} | ||
|
||
/** | ||
* Sessions save mode. Determines how session changes are tracked and saved to the | ||
* session store. | ||
*/ | ||
var saveMode: SaveMode | ||
get() = redisSessionProperties.saveMode | ||
set(value) { | ||
redisSessionProperties.saveMode = value | ||
} | ||
|
||
override fun initialize(context: GenericApplicationContext) { | ||
super.initialize(context) | ||
init() | ||
RedisReactiveSessionConfigurationInitializer(sessionProperties, redisSessionProperties).initialize(context) | ||
} | ||
} | ||
|
||
/** | ||
* @see ReactiveRedisDsl | ||
*/ | ||
fun SessionDsl.reactiveRedis(dsl: ReactiveRedisDsl.() -> Unit = {}) { | ||
val sessionProperties = configurationProperties(prefix = "spring.session", defaultProperties = SessionProperties()) | ||
val redisSessionProperties = configurationProperties(prefix = "spring.session.redis", defaultProperties = RedisSessionProperties()) | ||
ReactiveRedisDsl(dsl, sessionProperties, redisSessionProperties).initialize(context) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
42 changes: 42 additions & 0 deletions
42
kofu/src/test/kotlin/org/springframework/fu/kofu/TestUtils.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
/* | ||
* Copyright 2002-2020 the original author or authors. | ||
* | ||
* Licensed 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.springframework.fu.kofu | ||
|
||
import org.springframework.security.authentication.UserDetailsRepositoryReactiveAuthenticationManager | ||
import org.springframework.security.core.userdetails.MapReactiveUserDetailsService | ||
import org.springframework.security.core.userdetails.User | ||
import java.nio.charset.Charset | ||
import java.util.* | ||
|
||
fun userDetailsService(username: String, password: String): MapReactiveUserDetailsService { | ||
@Suppress("DEPRECATION") | ||
val user = User.withDefaultPasswordEncoder() | ||
.username(username) | ||
.password(password) | ||
.roles("USER") | ||
.build() | ||
return MapReactiveUserDetailsService(user) | ||
} | ||
|
||
val username = "user" | ||
val password = "password" | ||
fun repoAuthenticationManager(): UserDetailsRepositoryReactiveAuthenticationManager { | ||
return UserDetailsRepositoryReactiveAuthenticationManager(userDetailsService(username, password)) | ||
} | ||
|
||
fun basicAuth() = | ||
Base64.getEncoder().encode("$username:$password".toByteArray())?.toString(Charset.defaultCharset()) |
49 changes: 49 additions & 0 deletions
49
kofu/src/test/kotlin/org/springframework/fu/kofu/samples/session.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/* | ||
* Copyright 2012-2020 the original author or authors. | ||
* | ||
* Licensed 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.springframework.fu.kofu.samples | ||
|
||
import org.springframework.fu.kofu.reactiveWebApplication | ||
import org.springframework.fu.kofu.session.reactiveRedis | ||
import org.springframework.fu.kofu.webflux.security | ||
import org.springframework.fu.kofu.session.session | ||
import org.springframework.fu.kofu.webflux.webFlux | ||
import org.springframework.session.SaveMode | ||
import java.time.Duration | ||
|
||
fun sessionDsl() { | ||
reactiveWebApplication { | ||
session { | ||
reactiveRedis { | ||
maxInactiveIntervalInSeconds = Duration.ofSeconds(Long.MAX_VALUE) | ||
redisNamespace = "spring:session" // default | ||
saveMode = SaveMode.ON_SET_ATTRIBUTE // default | ||
} | ||
} | ||
security { | ||
http = { | ||
anonymous { } | ||
authorizeExchange { | ||
authorize("/view", hasRole("USER")) | ||
authorize("/public-view", permitAll) | ||
} | ||
headers {} | ||
logout {} | ||
} | ||
} | ||
webFlux { } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.