diff --git a/spring-session-docs/modules/ROOT/pages/configuration/jdbc.adoc b/spring-session-docs/modules/ROOT/pages/configuration/jdbc.adoc index 07b72eac8..7406949ef 100644 --- a/spring-session-docs/modules/ROOT/pages/configuration/jdbc.adoc +++ b/spring-session-docs/modules/ROOT/pages/configuration/jdbc.adoc @@ -161,7 +161,7 @@ public class QueryCustomizer private static final String UPDATE_SESSION_ATTRIBUTE_QUERY = """ UPDATE %TABLE_NAME%_ATTRIBUTES - SET ATTRIBUTE_BYTES = encode(?, 'escape')::jsonb + SET ATTRIBUTE_BYTES = convert_from(?, 'UTF8')::jsonb WHERE SESSION_PRIMARY_ID = ? AND ATTRIBUTE_NAME = ? """; @@ -309,12 +309,12 @@ public class SessionConfig { private static final String CREATE_SESSION_ATTRIBUTE_QUERY = """ INSERT INTO %TABLE_NAME%_ATTRIBUTES (SESSION_PRIMARY_ID, ATTRIBUTE_NAME, ATTRIBUTE_BYTES) - VALUES (?, ?, encode(?, 'escape')::jsonb) <1> + VALUES (?, ?, convert_from(?, 'UTF8')::jsonb) <1> """; private static final String UPDATE_SESSION_ATTRIBUTE_QUERY = """ UPDATE %TABLE_NAME%_ATTRIBUTES - SET ATTRIBUTE_BYTES = encode(?, 'escape')::jsonb + SET ATTRIBUTE_BYTES = convert_from(?, 'UTF8')::jsonb WHERE SESSION_PRIMARY_ID = ? AND ATTRIBUTE_NAME = ? """; diff --git a/spring-session-samples/spring-session-sample-boot-jdbc-json-attribute/src/main/java/sample/config/SessionConfig.java b/spring-session-samples/spring-session-sample-boot-jdbc-json-attribute/src/main/java/sample/config/SessionConfig.java index 817d17a05..5c9acc630 100644 --- a/spring-session-samples/spring-session-sample-boot-jdbc-json-attribute/src/main/java/sample/config/SessionConfig.java +++ b/spring-session-samples/spring-session-sample-boot-jdbc-json-attribute/src/main/java/sample/config/SessionConfig.java @@ -23,7 +23,7 @@ public class SessionConfig implements BeanClassLoaderAware { private static final String CREATE_SESSION_ATTRIBUTE_QUERY = """ INSERT INTO %TABLE_NAME%_ATTRIBUTES (SESSION_PRIMARY_ID, ATTRIBUTE_NAME, ATTRIBUTE_BYTES) - VALUES (?, ?, encode(?, 'escape')::jsonb) + VALUES (?, ?, convert_from(?, 'UTF8')::jsonb) """; private static final String UPDATE_SESSION_ATTRIBUTE_QUERY = """ diff --git a/spring-session-samples/spring-session-sample-boot-jdbc-json-attribute/src/test/java/sample/JdbcJsonAttributeTests.java b/spring-session-samples/spring-session-sample-boot-jdbc-json-attribute/src/test/java/sample/JdbcJsonAttributeTests.java index 0a1ee9cb3..25abb6a1a 100644 --- a/spring-session-samples/spring-session-sample-boot-jdbc-json-attribute/src/test/java/sample/JdbcJsonAttributeTests.java +++ b/spring-session-samples/spring-session-sample-boot-jdbc-json-attribute/src/test/java/sample/JdbcJsonAttributeTests.java @@ -1,17 +1,14 @@ package sample; -import java.sql.Types; import java.util.Base64; -import java.util.List; -import java.util.Map; import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.servlet.http.Cookie; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.security.SecurityProperties; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Import; @@ -40,6 +37,13 @@ class JdbcJsonAttributeTests { @Autowired JdbcClient jdbcClient; + String username; + + @Autowired + void setSecurityProperties(SecurityProperties securityProperties) { + this.username = securityProperties.getUser().getName(); + } + @BeforeEach void setup() { ObjectMapper copy = this.objectMapper.copy(); @@ -51,7 +55,7 @@ void setup() { @Test void loginShouldSaveSecurityContextAsJson() throws Exception { - Cookie sessionCookie = this.mvc.perform(formLogin().user("user").password("password")) + Cookie sessionCookie = this.mvc.perform(formLogin().user(this.username).password("password")) .andExpect(authenticated()) .andReturn() .getResponse() @@ -66,20 +70,20 @@ void loginShouldSaveSecurityContextAsJson() throws Exception { SecurityContext securityContext = this.objectMapperWithModules.readValue((String) attributeBytes, SecurityContext.class); assertThat(securityContext).isNotNull(); - assertThat(securityContext.getAuthentication().getName()).isEqualTo("user"); + assertThat(securityContext.getAuthentication().getName()).isEqualTo(this.username); } @Test void loginWhenQueryUsingJsonbOperatorThenReturns() throws Exception { - this.mvc.perform(formLogin().user("user").password("password")).andExpect(authenticated()); + this.mvc.perform(formLogin().user(this.username).password("password")).andExpect(authenticated()); Object attributeBytes = this.jdbcClient.sql(""" SELECT attribute_bytes::text FROM spring_session_attributes - WHERE attribute_bytes -> 'authentication' -> 'principal' ->> 'username' = 'user' - """).query().singleValue(); + WHERE attribute_bytes -> 'authentication' -> 'principal' ->> 'username' = '%s' + """.formatted(this.username)).query().singleValue(); SecurityContext securityContext = this.objectMapperWithModules.readValue((String) attributeBytes, SecurityContext.class); assertThat(securityContext).isNotNull(); - assertThat(securityContext.getAuthentication().getName()).isEqualTo("user"); + assertThat(securityContext.getAuthentication().getName()).isEqualTo(this.username); } } diff --git a/spring-session-samples/spring-session-sample-boot-jdbc-json-attribute/src/test/java/sample/JdbcJsonSpecialCharsAttributeTests.java b/spring-session-samples/spring-session-sample-boot-jdbc-json-attribute/src/test/java/sample/JdbcJsonSpecialCharsAttributeTests.java new file mode 100644 index 000000000..00b1c1e7f --- /dev/null +++ b/spring-session-samples/spring-session-sample-boot-jdbc-json-attribute/src/test/java/sample/JdbcJsonSpecialCharsAttributeTests.java @@ -0,0 +1,29 @@ +/* + * Copyright 2014-2022 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 + * + * https://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 sample; + +import org.springframework.test.context.TestPropertySource; + +/** + * Test that special characters in usernames work. + * + * @author Rob Winch + */ +@TestPropertySource(properties = "spring.security.user.name=rüdiger") +class JdbcJsonSpecialCharsAttributeTests extends JdbcJsonAttributeTests { + +}