-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
642 additions
and
0 deletions.
There are no files selected for viewing
31 changes: 31 additions & 0 deletions
31
...amples/spring-session-sample-javaconfig-rest/spring-session-sample-javaconfig-rest.gradle
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,31 @@ | ||
plugins { | ||
id "org.gretty" version "4.0.0" | ||
id "io.spring.convention.spring-sample-war" | ||
} | ||
|
||
dependencies { | ||
implementation project(':spring-session-data-redis') | ||
implementation "io.lettuce:lettuce-core" | ||
implementation "org.springframework:spring-webmvc" | ||
implementation "org.springframework.security:spring-security-config" | ||
implementation "org.springframework.security:spring-security-web" | ||
implementation "com.fasterxml.jackson.core:jackson-databind" | ||
implementation "org.slf4j:slf4j-api" | ||
implementation "org.slf4j:jcl-over-slf4j" | ||
implementation "org.slf4j:log4j-over-slf4j" | ||
implementation "ch.qos.logback:logback-classic" | ||
implementation "org.testcontainers:testcontainers" | ||
|
||
providedCompile "jakarta.servlet:jakarta.servlet-api:6.0.0" | ||
|
||
testImplementation "org.springframework.security:spring-security-test" | ||
testImplementation "org.assertj:assertj-core" | ||
testImplementation "org.springframework:spring-test" | ||
testImplementation "org.junit.jupiter:junit-jupiter-api" | ||
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine" | ||
} | ||
|
||
gretty { | ||
jvmArgs = ['-Dspring.profiles.active=embedded-redis'] | ||
servletContainer = 'tomcat10' | ||
} |
112 changes: 112 additions & 0 deletions
112
...pring-session-sample-javaconfig-rest/src/integration-test/java/rest/RestMockMvcTests.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,112 @@ | ||
/* | ||
* 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 rest; | ||
|
||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.extension.ExtendWith; | ||
import org.testcontainers.containers.GenericContainer; | ||
import sample.SecurityConfig; | ||
import sample.mvc.MvcConfig; | ||
|
||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; | ||
import org.springframework.security.test.context.support.WithMockUser; | ||
import org.springframework.session.Session; | ||
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; | ||
import org.springframework.session.web.http.HeaderHttpSessionIdResolver; | ||
import org.springframework.session.web.http.HttpSessionIdResolver; | ||
import org.springframework.session.web.http.SessionRepositoryFilter; | ||
import org.springframework.test.context.ContextConfiguration; | ||
import org.springframework.test.context.junit.jupiter.SpringExtension; | ||
import org.springframework.test.context.web.WebAppConfiguration; | ||
import org.springframework.test.web.servlet.MockMvc; | ||
import org.springframework.test.web.servlet.setup.MockMvcBuilders; | ||
import org.springframework.web.context.WebApplicationContext; | ||
|
||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; | ||
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; | ||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; | ||
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; | ||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; | ||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; | ||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | ||
|
||
@ExtendWith(SpringExtension.class) | ||
@ContextConfiguration(classes = { RestMockMvcTests.Config.class, SecurityConfig.class, MvcConfig.class }) | ||
@WebAppConfiguration | ||
class RestMockMvcTests { | ||
|
||
private static final String DOCKER_IMAGE = "redis:7.0.4-alpine"; | ||
|
||
@Autowired | ||
private SessionRepositoryFilter<? extends Session> sessionRepositoryFilter; | ||
|
||
@Autowired | ||
private WebApplicationContext context; | ||
|
||
private MockMvc mvc; | ||
|
||
@BeforeEach | ||
void setup() { | ||
this.mvc = MockMvcBuilders.webAppContextSetup(this.context).alwaysDo(print()) | ||
.addFilters(this.sessionRepositoryFilter).apply(springSecurity()).build(); | ||
} | ||
|
||
@Test | ||
void noSessionOnNoCredentials() throws Exception { | ||
this.mvc.perform(get("/")).andExpect(header().doesNotExist("X-Auth-Token")) | ||
.andExpect(status().isUnauthorized()); | ||
} | ||
|
||
@WithMockUser | ||
@Test | ||
void autheticatedAnnotation() throws Exception { | ||
this.mvc.perform(get("/")).andExpect(content().string("{\"username\":\"user\"}")); | ||
} | ||
|
||
@Test | ||
void autheticatedRequestPostProcessor() throws Exception { | ||
this.mvc.perform(get("/").with(user("user"))).andExpect(content().string("{\"username\":\"user\"}")); | ||
} | ||
|
||
@Configuration | ||
@EnableRedisHttpSession | ||
static class Config { | ||
|
||
@Bean | ||
GenericContainer redisContainer() { | ||
GenericContainer redisContainer = new GenericContainer(DOCKER_IMAGE).withExposedPorts(6379); | ||
redisContainer.start(); | ||
return redisContainer; | ||
} | ||
|
||
@Bean | ||
LettuceConnectionFactory redisConnectionFactory() { | ||
return new LettuceConnectionFactory(redisContainer().getHost(), redisContainer().getFirstMappedPort()); | ||
} | ||
|
||
@Bean | ||
HttpSessionIdResolver httpSessionIdResolver() { | ||
return HeaderHttpSessionIdResolver.xAuthToken(); | ||
} | ||
|
||
} | ||
|
||
} |
125 changes: 125 additions & 0 deletions
125
...les/spring-session-sample-javaconfig-rest/src/integration-test/java/sample/RestTests.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,125 @@ | ||
/* | ||
* Copyright 2014-2019 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 java.util.Base64; | ||
import java.util.Collections; | ||
|
||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import org.springframework.http.HttpEntity; | ||
import org.springframework.http.HttpHeaders; | ||
import org.springframework.http.HttpMethod; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.MediaType; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.client.HttpClientErrorException; | ||
import org.springframework.web.client.RestTemplate; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType; | ||
|
||
/** | ||
* @author Pool Dolorier | ||
*/ | ||
class RestTests { | ||
|
||
private static final String AUTHORIZATION = "Authorization"; | ||
|
||
private static final String BASIC = "Basic "; | ||
|
||
private static final String X_AUTH_TOKEN = "X-Auth-Token"; | ||
|
||
private RestTemplate restTemplate; | ||
|
||
private String baseUrl; | ||
|
||
@BeforeEach | ||
void setUp() { | ||
this.baseUrl = "http://localhost:" + System.getProperty("app.port"); | ||
this.restTemplate = new RestTemplate(); | ||
} | ||
|
||
@Test | ||
void unauthenticatedUserSentToLogInPage() { | ||
HttpHeaders headers = new HttpHeaders(); | ||
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); | ||
assertThatExceptionOfType(HttpClientErrorException.class) | ||
.isThrownBy(() -> getForUser(this.baseUrl + "/", headers, String.class)) | ||
.satisfies((e) -> assertThat(e.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED)); | ||
} | ||
|
||
@Test | ||
void authenticateWithBasicWorks() { | ||
String auth = getAuth("user", "password"); | ||
HttpHeaders headers = getHttpHeaders(); | ||
headers.set(AUTHORIZATION, BASIC + auth); | ||
ResponseEntity<User> entity = getForUser(this.baseUrl + "/", headers, User.class); | ||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); | ||
assertThat(entity.getHeaders().containsKey(X_AUTH_TOKEN)).isTrue(); | ||
assertThat(entity.getBody().getUsername()).isEqualTo("user"); | ||
} | ||
|
||
@Test | ||
void authenticateWithXAuthTokenWorks() { | ||
String auth = getAuth("user", "password"); | ||
HttpHeaders headers = getHttpHeaders(); | ||
headers.set(AUTHORIZATION, BASIC + auth); | ||
ResponseEntity<User> entity = getForUser(this.baseUrl + "/", headers, User.class); | ||
|
||
String token = entity.getHeaders().getFirst(X_AUTH_TOKEN); | ||
|
||
HttpHeaders authTokenHeader = new HttpHeaders(); | ||
authTokenHeader.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); | ||
authTokenHeader.set(X_AUTH_TOKEN, token); | ||
ResponseEntity<User> authTokenResponse = getForUser(this.baseUrl + "/", authTokenHeader, User.class); | ||
assertThat(authTokenResponse.getStatusCode()).isEqualTo(HttpStatus.OK); | ||
assertThat(authTokenResponse.getBody().getUsername()).isEqualTo("user"); | ||
} | ||
|
||
@Test | ||
void logout() { | ||
String auth = getAuth("user", "password"); | ||
HttpHeaders headers = getHttpHeaders(); | ||
headers.set(AUTHORIZATION, BASIC + auth); | ||
ResponseEntity<User> entity = getForUser(this.baseUrl + "/", headers, User.class); | ||
|
||
String token = entity.getHeaders().getFirst(X_AUTH_TOKEN); | ||
|
||
HttpHeaders logoutHeader = getHttpHeaders(); | ||
logoutHeader.set(X_AUTH_TOKEN, token); | ||
ResponseEntity<User> logoutResponse = getForUser(this.baseUrl + "/logout", logoutHeader, User.class); | ||
assertThat(logoutResponse.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT); | ||
} | ||
|
||
private <T> ResponseEntity<T> getForUser(String resourceUrl, HttpHeaders headers, Class<T> type) { | ||
return this.restTemplate.exchange(resourceUrl, HttpMethod.GET, new HttpEntity<T>(headers), type); | ||
} | ||
|
||
private HttpHeaders getHttpHeaders() { | ||
HttpHeaders headers = new HttpHeaders(); | ||
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); | ||
return headers; | ||
} | ||
|
||
private String getAuth(String user, String password) { | ||
String auth = user + ":" + password; | ||
return Base64.getEncoder().encodeToString(auth.getBytes()); | ||
} | ||
|
||
} |
34 changes: 34 additions & 0 deletions
34
...-samples/spring-session-sample-javaconfig-rest/src/integration-test/java/sample/User.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,34 @@ | ||
/* | ||
* Copyright 2014-2019 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; | ||
|
||
/** | ||
* @author Pool Dolorier | ||
*/ | ||
public class User { | ||
|
||
private String username; | ||
|
||
public String getUsername() { | ||
return this.username; | ||
} | ||
|
||
public void setUsername(String username) { | ||
this.username = username; | ||
} | ||
|
||
} |
46 changes: 46 additions & 0 deletions
46
...mples/spring-session-sample-javaconfig-rest/src/main/java/sample/EmbeddedRedisConfig.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,46 @@ | ||
/* | ||
* 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.testcontainers.containers.GenericContainer; | ||
|
||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.context.annotation.Primary; | ||
import org.springframework.context.annotation.Profile; | ||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; | ||
|
||
@Configuration | ||
@Profile("embedded-redis") | ||
public class EmbeddedRedisConfig { | ||
|
||
private static final String DOCKER_IMAGE = "redis:7.0.4-alpine"; | ||
|
||
@Bean | ||
public GenericContainer redisContainer() { | ||
GenericContainer redisContainer = new GenericContainer(DOCKER_IMAGE).withExposedPorts(6379); | ||
redisContainer.start(); | ||
return redisContainer; | ||
} | ||
|
||
@Bean | ||
@Primary | ||
public LettuceConnectionFactory redisConnectionFactory() { | ||
return new LettuceConnectionFactory(redisContainer().getHost(), redisContainer().getFirstMappedPort()); | ||
} | ||
|
||
} |
44 changes: 44 additions & 0 deletions
44
...samples/spring-session-sample-javaconfig-rest/src/main/java/sample/HttpSessionConfig.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,44 @@ | ||
/* | ||
* Copyright 2014-2019 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.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.context.annotation.Import; | ||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; | ||
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; | ||
import org.springframework.session.web.http.HeaderHttpSessionIdResolver; | ||
import org.springframework.session.web.http.HttpSessionIdResolver; | ||
|
||
@Import(EmbeddedRedisConfig.class) | ||
// tag::class[] | ||
@Configuration | ||
@EnableRedisHttpSession // <1> | ||
public class HttpSessionConfig { | ||
|
||
@Bean | ||
public LettuceConnectionFactory connectionFactory() { | ||
return new LettuceConnectionFactory(); // <2> | ||
} | ||
|
||
@Bean | ||
public HttpSessionIdResolver httpSessionIdResolver() { | ||
return HeaderHttpSessionIdResolver.xAuthToken(); // <3> | ||
} | ||
|
||
} | ||
// end::class[] |
Oops, something went wrong.