我对如何使用MongoDB Session和Spring Session处理属性感到困惑。我使用Redis时遇到了这个问题,但由于缺乏Spring的支持、几个池化错误以及Redis缓存的费用,这意味着我希望切换到MongoDB
我想将此保存为会话的属性,但不确定如何保存:
@Repository
internal class MongoAuthorizationRequestRepository(
private val mongoSerialiserConfig: MongoSerialiserConfig
) : ServerAuthorizationRequestRepository<OAuth2AuthorizationRequest> {
private val logger = LoggerFactory.getLogger(MongoSecurityContextRepository::class.java)
private val springAuthorizationRequestAttrName: String = "AUTHORIZATION_REQUEST"
override fun saveAuthorizationRequest(
authorizationRequest: OAuth2AuthorizationRequest?,
exchange: ServerWebExchange
): Mono<Void> {
logger.info("SAVING AUTHORIZATION REQUEST")
return exchange.session
.doOnNext { session ->
if (authorizationRequest?.state == null) {
logger.info("Authorization Request State cannot be empty")
} else {
session.attributes[springAuthorizationRequestAttrName] = authorizationRequest
logger.info("Authorization Request state: ${authorizationRequest.state}")
logger.info("Saved Authorization Request $authorizationRequest in WebSession: $session")
}
}.then()
}
override fun loadAuthorizationRequest(exchange: ServerWebExchange): Mono<OAuth2AuthorizationRequest?> {
logger.info("LOADING AUTHORIZATION REQUEST")
val state = getStateParameter(exchange) ?: return Mono.empty()
return exchange.session
.flatMap { session ->
val authorizationRequest = getAuthorizationRequest(session)
if (state == authorizationRequest?.state) {
logger.info("Loading authorization request")
Mono.just(authorizationRequest)
} else {
logger.warn("State in request does not match Authorization Request state in Session: $session")
Mono.empty()
}
}
}
override fun removeAuthorizationRequest(exchange: ServerWebExchange): Mono<OAuth2AuthorizationRequest?> {
logger.info("REMOVING AUTHORIZATION REQUEST")
val state = getStateParameter(exchange) ?: return Mono.empty()
return exchange.session
.flatMap { session ->
val authorizationRequest = getAuthorizationRequest(session)
if (state == authorizationRequest?.state) {
session.attributes.remove(this.springAuthorizationRequestAttrName)
logger.info("Removed authorization request")
Mono.just(authorizationRequest)
} else {
logger.info("State in request does not match Authorization Request state in Session: $session")
Mono.empty()
}
}
}
// Helper methods
private fun getStateParameter(exchange: ServerWebExchange): String? {
requireNotNull(exchange) { "exchange cannot be null" }
return exchange.request.queryParams[OAuth2ParameterNames.STATE]?.firstOrNull()
}
private fun getAuthorizationRequest(session: WebSession): OAuth2AuthorizationRequest? {
Assert.notNull(session, "session cannot be null")
val authRequestAttr = session.getAttribute<Map<String, Any>>(springAuthorizationRequestAttrName)
if (authRequestAttr != null) {
// Deserialize from Map to SecurityContext
val map = authRequestAttr as? Map<String, Any>
try {
val authorizationRequest = mongoSerialiserConfig.customObjectMapper()
.convertValue(map, OAuth2AuthorizationRequest::class.java)
logger.info("Successfully deserialized Authorization Request: $authorizationRequest")
return authorizationRequest
} catch (e: Exception) {
logger.error("Error deserializing Authorization Request: ${e.message}", e)
return null
}
} else {
logger.warn("No Authorization Request found in WebSession")
return null
}
}
}
已有2个转换器可用:
https://github.com/spring-projects/spring-session/blob/main/spring-session-data-mongodb/src/main/java/org/springframework/session/data/mongo/JacksonMongoSessionConverter.java
https://github.com/spring-projects/spring-session/blob/main/spring-session-data-mongodb/src/main/java/org/springframework/session/data/mongo/JdkMongoSessionConverter.java
fun jdkMongoSessionConverter(): JdkMongoSessionConverter {
val converter = JdkMongoSessionConverter(Duration.ofMinutes(7200))
return converter
}
@Bean
fun jacksonMongoSessionConverter(
mongoSerialiserConfig: MongoSerialiserConfig
): JacksonMongoSessionConverter {
return JacksonMongoSessionConverter(mongoSerialiserConfig.customObjectMapper())
}
我在第二个名为customObjectMapper的对象映射器中添加了一个自定义对象映射器。这篇文章允许的代码太多,所以可以在这里找到:
https://github.com/dreamstar-enterprises/docs/blob/master/Spring%20BFF/bff/auth/serialisers/MongoSerialiserConfig.kt
但我遇到的问题是,转换器使用MongoSession和docDB,而不是来自交易所的Websession。那么,你是如何序列化和去序列化的呢?
有什么想法吗?