parent
							
								
									31025d9f6c
								
							
						
					
					
						commit
						a8c027ba8e
					
				| 
						 | 
				
			
			@ -67,6 +67,7 @@
 | 
			
		|||
		<module>spring-boot-sample-secure-webflux</module>
 | 
			
		||||
		<module>spring-boot-sample-servlet</module>
 | 
			
		||||
		<module>spring-boot-sample-session</module>
 | 
			
		||||
		<module>spring-boot-sample-session-webflux</module>
 | 
			
		||||
		<module>spring-boot-sample-simple</module>
 | 
			
		||||
		<module>spring-boot-sample-test</module>
 | 
			
		||||
		<module>spring-boot-sample-test-nomockito</module>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,37 @@
 | 
			
		|||
= Spring Boot Spring Session Sample
 | 
			
		||||
 | 
			
		||||
This sample demonstrates the Spring Session WebFlux auto-configuration support. Spring
 | 
			
		||||
Session supports multiple reactive session store types, including:
 | 
			
		||||
 | 
			
		||||
* `Redis`
 | 
			
		||||
* `MongoDB`
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
== Using a different session store
 | 
			
		||||
Initially, the project uses MongoDB session store backed by an embedded MongoDB. You can
 | 
			
		||||
try out your favorite session store as explained below.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=== Redis
 | 
			
		||||
Add `org.springframework.session:spring-session-data-redis` and
 | 
			
		||||
`spring-boot-starter-data-redis-reactive` dependencies to the project and make sure it is
 | 
			
		||||
configured properly (by default, a Redis instance with the default settings is expected
 | 
			
		||||
on your local box).
 | 
			
		||||
 | 
			
		||||
TIP: Run sample application using Redis session store using
 | 
			
		||||
`$mvn spring-boot:run -Predis`.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=== MongoDB
 | 
			
		||||
Add `org.springframework.session:spring-session-data-mongodb` and
 | 
			
		||||
`spring-boot-starter-data-mongodb-reactive` and
 | 
			
		||||
`de.flapdoodle.embed:de.flapdoodle.embed.mongo` dependencies to the project. An embedded
 | 
			
		||||
MongoDB is automatically configured.
 | 
			
		||||
 | 
			
		||||
TIP: Run sample application using MongoDB session store using
 | 
			
		||||
`$mvn spring-boot:run -Pmongodb`.
 | 
			
		||||
 | 
			
		||||
Note that this profile is active by default.
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,76 @@
 | 
			
		|||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 | 
			
		||||
	<modelVersion>4.0.0</modelVersion>
 | 
			
		||||
	<parent>
 | 
			
		||||
		<!-- Your own application should inherit from spring-boot-starter-parent -->
 | 
			
		||||
		<groupId>org.springframework.boot</groupId>
 | 
			
		||||
		<artifactId>spring-boot-samples</artifactId>
 | 
			
		||||
		<version>${revision}</version>
 | 
			
		||||
	</parent>
 | 
			
		||||
	<artifactId>spring-boot-sample-session-webflux</artifactId>
 | 
			
		||||
	<name>Spring Boot Session WebFlux Sample</name>
 | 
			
		||||
	<description>Spring Boot Session WebFlux Sample</description>
 | 
			
		||||
	<properties>
 | 
			
		||||
		<main.basedir>${basedir}/../..</main.basedir>
 | 
			
		||||
	</properties>
 | 
			
		||||
	<dependencies>
 | 
			
		||||
		<!-- Compile -->
 | 
			
		||||
		<dependency>
 | 
			
		||||
			<groupId>org.springframework.boot</groupId>
 | 
			
		||||
			<artifactId>spring-boot-starter-webflux</artifactId>
 | 
			
		||||
		</dependency>
 | 
			
		||||
		<dependency>
 | 
			
		||||
			<groupId>org.springframework.boot</groupId>
 | 
			
		||||
			<artifactId>spring-boot-starter-security</artifactId>
 | 
			
		||||
		</dependency>
 | 
			
		||||
		<!-- Test -->
 | 
			
		||||
		<dependency>
 | 
			
		||||
			<groupId>org.springframework.boot</groupId>
 | 
			
		||||
			<artifactId>spring-boot-starter-test</artifactId>
 | 
			
		||||
			<scope>test</scope>
 | 
			
		||||
		</dependency>
 | 
			
		||||
	</dependencies>
 | 
			
		||||
	<build>
 | 
			
		||||
		<plugins>
 | 
			
		||||
			<plugin>
 | 
			
		||||
				<groupId>org.springframework.boot</groupId>
 | 
			
		||||
				<artifactId>spring-boot-maven-plugin</artifactId>
 | 
			
		||||
			</plugin>
 | 
			
		||||
		</plugins>
 | 
			
		||||
	</build>
 | 
			
		||||
	<profiles>
 | 
			
		||||
		<profile>
 | 
			
		||||
			<id>redis</id>
 | 
			
		||||
			<dependencies>
 | 
			
		||||
				<dependency>
 | 
			
		||||
					<groupId>org.springframework.session</groupId>
 | 
			
		||||
					<artifactId>spring-session-data-redis</artifactId>
 | 
			
		||||
				</dependency>
 | 
			
		||||
				<dependency>
 | 
			
		||||
					<groupId>org.springframework.boot</groupId>
 | 
			
		||||
					<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
 | 
			
		||||
				</dependency>
 | 
			
		||||
			</dependencies>
 | 
			
		||||
		</profile>
 | 
			
		||||
		<profile>
 | 
			
		||||
			<id>mongodb</id>
 | 
			
		||||
			<activation>
 | 
			
		||||
				<activeByDefault>true</activeByDefault>
 | 
			
		||||
			</activation>
 | 
			
		||||
			<dependencies>
 | 
			
		||||
				<dependency>
 | 
			
		||||
					<groupId>org.springframework.session</groupId>
 | 
			
		||||
					<artifactId>spring-session-data-mongodb</artifactId>
 | 
			
		||||
				</dependency>
 | 
			
		||||
				<dependency>
 | 
			
		||||
					<groupId>org.springframework.boot</groupId>
 | 
			
		||||
					<artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
 | 
			
		||||
				</dependency>
 | 
			
		||||
				<dependency>
 | 
			
		||||
					<groupId>de.flapdoodle.embed</groupId>
 | 
			
		||||
					<artifactId>de.flapdoodle.embed.mongo</artifactId>
 | 
			
		||||
				</dependency>
 | 
			
		||||
			</dependencies>
 | 
			
		||||
		</profile>
 | 
			
		||||
	</profiles>
 | 
			
		||||
</project>
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,31 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright 2012-2017 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 sample.session;
 | 
			
		||||
 | 
			
		||||
import org.springframework.web.bind.annotation.GetMapping;
 | 
			
		||||
import org.springframework.web.bind.annotation.RestController;
 | 
			
		||||
import org.springframework.web.server.WebSession;
 | 
			
		||||
 | 
			
		||||
@RestController
 | 
			
		||||
public class HelloRestController {
 | 
			
		||||
 | 
			
		||||
	@GetMapping("/")
 | 
			
		||||
	String sessionId(WebSession session) {
 | 
			
		||||
		return session.getId();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,57 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright 2012-2017 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 sample.session;
 | 
			
		||||
 | 
			
		||||
import org.springframework.boot.SpringApplication;
 | 
			
		||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
 | 
			
		||||
import org.springframework.context.annotation.Bean;
 | 
			
		||||
import org.springframework.security.config.web.server.ServerHttpSecurity;
 | 
			
		||||
import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;
 | 
			
		||||
import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
 | 
			
		||||
import org.springframework.security.core.userdetails.User;
 | 
			
		||||
import org.springframework.security.web.server.SecurityWebFilterChain;
 | 
			
		||||
import org.springframework.security.web.server.context.WebSessionServerSecurityContextRepository;
 | 
			
		||||
 | 
			
		||||
@SpringBootApplication
 | 
			
		||||
public class SampleSessionWebFluxApplication {
 | 
			
		||||
 | 
			
		||||
	public static void main(String[] args) {
 | 
			
		||||
		SpringApplication.run(SampleSessionWebFluxApplication.class);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Bean
 | 
			
		||||
	public ReactiveUserDetailsService userDetailsRepository() {
 | 
			
		||||
		return new MapReactiveUserDetailsService(User.withDefaultPasswordEncoder()
 | 
			
		||||
				.username("user").password("password").roles("USER").build());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Bean
 | 
			
		||||
	public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
 | 
			
		||||
		// @formatter:off
 | 
			
		||||
		return http
 | 
			
		||||
			.authorizeExchange()
 | 
			
		||||
				.anyExchange().authenticated()
 | 
			
		||||
				.and()
 | 
			
		||||
			.httpBasic().securityContextRepository(new WebSessionServerSecurityContextRepository())
 | 
			
		||||
				.and()
 | 
			
		||||
			.formLogin()
 | 
			
		||||
				.and()
 | 
			
		||||
			.build();
 | 
			
		||||
		// @formatter:on
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,77 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright 2012-2017 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 sample.session;
 | 
			
		||||
 | 
			
		||||
import java.util.Base64;
 | 
			
		||||
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.junit.runner.RunWith;
 | 
			
		||||
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.boot.test.context.SpringBootTest;
 | 
			
		||||
import org.springframework.boot.web.server.LocalServerPort;
 | 
			
		||||
import org.springframework.http.HttpStatus;
 | 
			
		||||
import org.springframework.http.ResponseCookie;
 | 
			
		||||
import org.springframework.test.context.junit4.SpringRunner;
 | 
			
		||||
import org.springframework.web.reactive.function.client.ClientResponse;
 | 
			
		||||
import org.springframework.web.reactive.function.client.WebClient;
 | 
			
		||||
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Integration tests for {@link SampleSessionWebFluxApplication}.
 | 
			
		||||
 *
 | 
			
		||||
 * @author Vedran Pavic
 | 
			
		||||
 */
 | 
			
		||||
@RunWith(SpringRunner.class)
 | 
			
		||||
@SpringBootTest(properties = "server.session.timeout:1", webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
 | 
			
		||||
public class SampleSessionWebFluxApplicationTests {
 | 
			
		||||
 | 
			
		||||
	@LocalServerPort
 | 
			
		||||
	private int port;
 | 
			
		||||
 | 
			
		||||
	@Autowired
 | 
			
		||||
	private WebClient.Builder webClientBuilder;
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void userDefinedMappingsSecureByDefault() throws Exception {
 | 
			
		||||
		WebClient webClient = this.webClientBuilder
 | 
			
		||||
				.baseUrl("http://localhost:" + this.port + "/").build();
 | 
			
		||||
 | 
			
		||||
		ClientResponse response = webClient.get().header("Authorization", getBasicAuth())
 | 
			
		||||
				.exchange().block();
 | 
			
		||||
		assertThat(response.statusCode()).isEqualTo(HttpStatus.OK);
 | 
			
		||||
		ResponseCookie sessionCookie = response.cookies().getFirst("SESSION");
 | 
			
		||||
		String sessionId = response.bodyToMono(String.class).block();
 | 
			
		||||
 | 
			
		||||
 		response = webClient.get().cookie("SESSION", sessionCookie.getValue()).exchange()
 | 
			
		||||
				.block();
 | 
			
		||||
		assertThat(response.statusCode()).isEqualTo(HttpStatus.OK);
 | 
			
		||||
		assertThat(response.bodyToMono(String.class).block()).isEqualTo(sessionId);
 | 
			
		||||
 | 
			
		||||
		Thread.sleep(1000);
 | 
			
		||||
 | 
			
		||||
		response = webClient.get().cookie("SESSION", sessionCookie.getValue()).exchange()
 | 
			
		||||
				.block();
 | 
			
		||||
		assertThat(response.statusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private String getBasicAuth() {
 | 
			
		||||
		return "Basic " + Base64.getEncoder().encodeToString("user:password".getBytes());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue