Compare commits

..

1 Commits

Author SHA1 Message Date
Spring Buildmaster
a8e6a973ab Release version 1.0.1.RELEASE 2015-04-15 13:43:14 -07:00
48 changed files with 374 additions and 389 deletions

3
.gitignore vendored
View File

@@ -8,5 +8,4 @@ bin
.project
target
out
.springBeans
*.rdb
.springBeans

View File

@@ -11,7 +11,7 @@ Spring Session aims to provide a common infrastructure for managing sessions. Th
= Spring Session Project Site
You can find the documentation, issue management, support, samples, and guides for using Spring Session at http://projects.spring.io/spring-session/
You can find the documentation, issue management, support, samples, and guides for using Spring Session at http://spring.io/spring-session/
= License

View File

@@ -5,7 +5,7 @@ buildscript {
dependencies {
classpath("org.gradle.api.plugins:gradle-tomcat-plugin:1.2.3")
classpath("org.springframework.build.gradle:propdeps-plugin:0.0.7")
classpath("io.spring.gradle:spring-io-plugin:0.0.4.RELEASE")
classpath("org.springframework.build.gradle:spring-io-plugin:0.0.3.RELEASE")
classpath('me.champeau.gradle:gradle-javadoc-hotfix-plugin:0.1')
classpath 'org.asciidoctor:asciidoctor-gradle-plugin:1.5.2'
}
@@ -15,7 +15,6 @@ group = 'org.springframework.session'
ext.springBootVersion = '1.2.3.RELEASE'
ext.JAVA_GRADLE = "$rootDir/gradle/java.gradle"
ext.SPRING3_GRADLE = "$rootDir/gradle/spring3.gradle"
ext.MAVEN_GRADLE = "$rootDir/gradle/publish-maven.gradle"
ext.TOMCAT_GRADLE = "$rootDir/gradle/tomcat.gradle"
ext.TOMCAT_6_GRADLE = "$rootDir/gradle/tomcat6.gradle"

View File

@@ -82,9 +82,8 @@ In this instance Spring Session is backed by Redis.
[[boot-redis-configuration]]
== Configuring the Redis Connection
Spring Boot automatically creates a `RedisConnectionFactory` that connects Spring Session to a Redis Server on localhost on port 6379 (default port).
In a production environment you need to ensure to update your configuration to point to your Redis server.
For example, you can include the following in your *application.properties*
Spring Boot automatically creates a `RedisConnectionFactory` that connects Spring Session to the Redis Server.
In a production environment you need to ensure to update your configuration to point to your Redis server. For example, you can include the following in your *application.properties*
.src/main/resources/application.properties
----
@@ -115,12 +114,6 @@ The boot Sample Application demonstrates how to use Spring Session to transparen
You can run the sample by obtaining the {download-url}[source code] and invoking the following command:
[NOTE]
====
For the sample to work, you must http://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
Alternatively, you can update the `JedisConnectionFactory` to point to a Redis server.
====
----
$ ./gradlew :samples:boot:bootRun
----

View File

@@ -21,7 +21,7 @@ If you are using Maven, ensure to add the following dependencies:
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
<version>{spring-session-version}</version>
<type>pom</type>
<type>pom<type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
@@ -79,12 +79,14 @@ Add the following Spring Configuration:
include::{samples-dir}httpsession-xml/src/main/webapp/WEB-INF/spring/session.xml[tags=beans]
----
<1> We use the combination of `<context:annotation-config/>` and `RedisHttpSessionConfiguration` because Spring Session does not yet provide XML Namespace support (see https://github.com/spring-projects/spring-session/issues/104[gh-104]).
<1> We create an embedded Redis Server so that there is no need to start up Redis external of our application.
In a production application this is not necessary since we would point our connection to an external Redis instance.
<2> We use the combination of `<context:annotation-config/>` and `RedisHttpSessionConfiguration` because Spring Session does not yet provide XML Namespace support (see https://github.com/spring-projects/spring-session/issues/104[gh-104]).
This creates a Spring Bean with the name of `springSessionRepositoryFilter` that implements Filter.
The filter is what is in charge of replacing the `HttpSession` implementation to be backed by Spring Session.
In this instance Spring Session is backed by Redis.
<2> We create a `RedisConnectionFactory` that connects Spring Session to the Redis Server.
We configure the connection to connect to localhost on the default port (6379)
<3> We create a `RedisConnectionFactory` that connects Spring Session to the Redis Server.
We use a http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#xsd-config-body-schemas-context-pphc[PropertyPlaceholderConfigurer] to externalize the port location.
For more information on configuring Spring Data Redis, refer to the http://docs.spring.io/spring-data/data-redis/docs/current/reference/html/[reference documentation].
== XML Servlet Container Initialization
@@ -126,12 +128,6 @@ For every request that `DelegatingFilterProxy` is invoked, the `springSessionRep
You can run the sample by obtaining the {download-url}[source code] and invoking the following command:
[NOTE]
====
For the sample to work, you must http://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
Alternatively, you can update the `JedisConnectionFactory` to point to a Redis server.
====
----
$ ./gradlew :samples:httpsession-xml:tomcatRun
----

View File

@@ -21,7 +21,7 @@ If you are using Maven, ensure to add the following dependencies:
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
<version>{spring-session-version}</version>
<type>pom</type>
<type>pom<type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
@@ -78,11 +78,13 @@ Add the following Spring Configuration:
include::{samples-dir}httpsession/src/main/java/sample/Config.java[tags=class]
----
<1> The `@EnableRedisHttpSession` annotation creates a Spring Bean with the name of `springSessionRepositoryFilter` that implements Filter.
<1> We import an embedded Redis Server so that there is no need to start up Redis external of our application.
In a production application this is not necessary since we would point our connection to an external Redis instance.
<2> The `@EnableRedisHttpSession` annotation creates a Spring Bean with the name of `springSessionRepositoryFilter` that implements Filter.
The filter is what is in charge of replacing the `HttpSession` implementation to be backed by Spring Session.
In this instance Spring Session is backed by Redis.
<2> We create a `RedisConnectionFactory` that connects Spring Session to the Redis Server.
We configure the connection to connect to localhost on the default port (6379)
<3> We create a `RedisConnectionFactory` that connects Spring Session to the Redis Server.
We use a http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#xsd-config-body-schemas-context-pphc[PropertyPlaceholderConfigurer] to externalize the port location.
For more information on configuring Spring Data Redis, refer to the http://docs.spring.io/spring-data/data-redis/docs/current/reference/html/[reference documentation].
== Java Servlet Container Initialization
@@ -118,12 +120,6 @@ This ensures that the Spring Bean by the name `springSessionRepositoryFilter` is
You can run the sample by obtaining the {download-url}[source code] and invoking the following command:
[NOTE]
====
For the sample to work, you must http://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
Alternatively, you can update the `JedisConnectionFactory` to point to a Redis server.
====
----
$ ./gradlew :samples:httpsession:tomcatRun
----

View File

@@ -21,7 +21,7 @@ If you are using Maven, ensure to add the following dependencies:
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
<version>{spring-session-version}</version>
<type>pom</type>
<type>pom<type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
@@ -78,13 +78,15 @@ Add the following Spring Configuration:
include::{samples-dir}rest/src/main/java/sample/HttpSessionConfig.java[tags=class]
----
<1> The `@EnableRedisHttpSession` annotation creates a Spring Bean with the name of `springSessionRepositoryFilter` that implements `Filter`.
<1> We import an embedded Redis Server so that there is no need to start up Redis external of our application.
In a production application this is not necessary since we would point our connection to an external Redis instance.
<2> The `@EnableRedisHttpSession` annotation creates a Spring Bean with the name of `springSessionRepositoryFilter` that implements `Filter`.
The filter is what is in charge of replacing the `HttpSession` implementation to be backed by Spring Session.
In this instance Spring Session is backed by Redis.
<2> We create a `RedisConnectionFactory` that connects Spring Session to the Redis Server.
We configure the connection to connect to localhost on the default port (6379)
<3> We create a `RedisConnectionFactory` that connects Spring Session to the Redis Server.
In our example, we are connecting to localhost on the default port (6379).
For more information on configuring Spring Data Redis, refer to the http://docs.spring.io/spring-data/data-redis/docs/current/reference/html/[reference documentation].
<3> We customize Spring Session's HttpSession integration to use HTTP headers to convey the current session information instead of cookies.
<4> We customize Spring Session's HttpSession integration to use HTTP headers to convey the current session information instead of cookies.
== Servlet Container Initialization
@@ -119,12 +121,6 @@ NOTE: The name of our class (Initializer) does not matter. What is important is
You can run the sample by obtaining the {download-url}[source code] and invoking the following command:
[NOTE]
====
For the sample to work, you must http://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
Alternatively, you can update the `JedisConnectionFactory` to point to a Redis server.
====
----
$ ./gradlew :samples:rest:tomcatRun
----

View File

@@ -22,7 +22,7 @@ If you are using Maven, ensure to add the following dependencies:
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
<version>{spring-session-version}</version>
<type>pom</type>
<type>pom<type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
@@ -77,11 +77,13 @@ Add the following Spring Configuration:
include::{samples-dir}security/src/main/java/sample/Config.java[tags=class]
----
<1> The `@EnableRedisHttpSession` annotation creates a Spring Bean with the name of `springSessionRepositoryFilter` that implements Filter.
<1> We import an embedded Redis Server so that there is no need to start up Redis external of our application.
In a production application this is not necessary since we would point our connection to an external Redis instance.
<2> The `@EnableRedisHttpSession` annotation creates a Spring Bean with the name of `springSessionRepositoryFilter` that implements Filter.
The filter is what is in charge of replacing the `HttpSession` implementation to be backed by Spring Session.
In this instance Spring Session is backed by Redis.
<2> We create a `RedisConnectionFactory` that connects Spring Session to the Redis Server.
We configure the connection to connect to localhost on the default port (6379)
<3> We create a `RedisConnectionFactory` that connects Spring Session to the Redis Server.
In our example, we are connecting to localhost on the default port (6379).
For more information on configuring Spring Data Redis, refer to the http://docs.spring.io/spring-data/data-redis/docs/current/reference/html/[reference documentation].
== Servlet Container Initialization
@@ -123,12 +125,6 @@ By extending `AbstractHttpSessionApplicationInitializer` we ensure that the Spri
You can run the sample by obtaining the {download-url}[source code] and invoking the following command:
[NOTE]
====
For the sample to work, you must http://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
Alternatively, you can update the `JedisConnectionFactory` to point to a Redis server.
====
----
$ ./gradlew :samples:security:tomcatRun
----

View File

@@ -17,12 +17,6 @@ The users application demonstrates how to allow an application to manage multipl
You can run the sample by obtaining the {download-url}[source code] and invoking the following command:
[NOTE]
====
For the sample to work, you must http://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
Alternatively, you can update the `JedisConnectionFactory` to point to a Redis server.
====
----
$ ./gradlew :samples:users:tomcatRun
----

View File

@@ -82,12 +82,6 @@ include::{samples-dir}websocket/src/main/java/sample/config/WebSecurityConfig.ja
----
====
[NOTE]
====
For the sample to work, you must http://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
Alternatively, you can update the `JedisConnectionFactory` to point to a Redis server.
====
----
$ ./gradlew :samples:websocket:bootRun
----

View File

@@ -474,20 +474,3 @@ We appreciate https://help.github.com/articles/using-pull-requests/[Pull Request
=== License
Spring Session is Open Source software released under the http://www.apache.org/licenses/LICENSE-2.0.html[Apache 2.0 license].
[[minimum-requirements]]
== Minimum Requirements
The minimum requirements for Spring Session are:
* Java 5+
* If you are running in a Servlet Container (not required), Servlet 2.5+
* If you are using other Spring libraries (not required), the minimum required version is Spring 3.2.14.
While we re-run all unit tests against Spring 3.2.x, we recommend using the latest Spring 4.x version when possible.
* `@EnableRedisHttpSession` requires Redis 2.8+. This is necessary to support <<api-redisoperationssessionrepository-expiration,Session Expiration>>
[NOTE]
====
At its core Spring Session only has a required dependency on commons-logging.
For an example of using Spring Session without any other Spring dependencies, refer to the <<samples,hazelcast sample>> application.
====

View File

@@ -1,10 +1,11 @@
springSecurityVersion=4.0.0.RELEASE
embeddedRedisVersion=0.6
junitVersion=4.11
jstlVersion=1.2.1
jedisVersion=2.5.2
springVersion=4.1.6.RELEASE
groovyVersion=2.3.11
version=1.0.3.BUILD-SNAPSHOT
version=1.0.1.RELEASE
seleniumVersion=2.44.0
jacksonVersion=2.4.5
gebVersion=0.10.0

View File

@@ -73,7 +73,6 @@ task integrationTest(type: Test, dependsOn: jar) {
junitXml.destination = project.file("$project.buildDir/integration-test-results/")
}
}
check.dependsOn integrationTest
eclipse {
classpath {

View File

@@ -1,24 +0,0 @@
configurations {
spring3TestRuntime.extendsFrom testRuntime
}
configurations.spring3TestRuntime {
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
if (details.requested.group == 'org.springframework'
&& details.requested.name != 'spring-websocket'
&& details.requested.name != 'spring-messaging') {
details.useVersion '3.2.14.RELEASE'
}
}
}
task spring3Test(type: Test) {
jvmArgs = ['-ea', '-Xmx500m', '-XX:MaxPermSize=128M']
classpath = sourceSets.test.output + sourceSets.main.output + configurations.spring3TestRuntime
exclude "org/springframework/session/web/socket/**"
reports {
html.destination = project.file("$buildDir/spring3-test-results/")
junitXml.destination = project.file("$buildDir/reports/spring3-tests/")
}
}
check.dependsOn spring3Test

View File

@@ -17,6 +17,7 @@ group = 'samples'
dependencies {
compile project(':spring-session'),
project(':samples:spring-embedded-redis'),
"org.springframework.boot:spring-boot-starter-redis",
"org.springframework.boot:spring-boot-starter-web",
"org.springframework.boot:spring-boot-starter-thymeleaf",

View File

@@ -15,9 +15,11 @@
*/
package sample.config;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.session.data.redis.config.annotation.web.http.*;
import org.springframework.session.redis.embedded.EnableEmbeddedRedis;
@EnableEmbeddedRedis
// tag::class[]
@EnableRedisHttpSession // <1>
public class HttpSessionConfig { }

View File

@@ -13,13 +13,13 @@
<body>
<div class="container">
<h1>Description</h1>
<p>This application demonstrates how to use Hazelcast to back your session. Notice that there is no JSESSIONID cookie. We are also able to customize the way of identifying what the requested session id is.</p>
<p>This application demonstrates how to use a Redis instance to back your session. Notice that there is no JSESSIONID cookie. We are also able to customize the way of identifying what the requested session id is.</p>
<h1>Try it</h1>
<form class="form-inline" role="form" action="./session" method="post">
<label for="attributeName">Attribute Name</label>
<input id="attributeName" type="text" name="attributeName"/>
<label for="attributeValue">Attribute Name</label>
<input id="attributeValue" type="text" name="attributeName"/>
<label for="attributeValue">Attribute Value</label>
<input id="attributeValue" type="text" name="attributeValue"/>
<input type="submit" value="Set Attribute"/>

View File

@@ -8,6 +8,7 @@ sonarRunner {
dependencies {
compile project(':spring-session-data-redis'),
project(':samples:spring-embedded-redis'),
"org.springframework:spring-web:$springVersion",
jstlDependencies

View File

@@ -7,12 +7,14 @@
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- tag::beans[] -->
<bean class="org.springframework.session.redis.embedded.EmbeddedRedisConfiguration"/> <!--1-->
<!--1-->
<!--2-->
<context:annotation-config/>
<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"/>
<!--2-->
<bean class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"/>
<!--3-->
<bean class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:port="${spring.redis.port}"/>
<!-- end::beans[] -->
</beans>

View File

@@ -18,8 +18,8 @@
<h1>Try it</h1>
<form class="form-inline" role="form" action="./session" method="post">
<label for="attributeName">Attribute Name</label>
<input id="attributeName" type="text" name="attributeName"/>
<label for="attributeValue">Attribute Name</label>
<input id="attributeValue" type="text" name="attributeName"/>
<label for="attributeValue">Attribute Value</label>
<input id="attributeValue" type="text" name="attributeValue"/>
<input type="submit" value="Set Attribute"/>

View File

@@ -8,6 +8,7 @@ sonarRunner {
dependencies {
compile project(':spring-session-data-redis'),
project(':samples:spring-embedded-redis'),
"org.springframework:spring-web:$springVersion",
jstlDependencies

View File

@@ -18,14 +18,19 @@ package sample;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.session.redis.embedded.EnableEmbeddedRedis;
import org.springframework.session.redis.embedded.RedisServerPort;
// tag::class[]
@EnableRedisHttpSession // <1>
@EnableEmbeddedRedis // <1>
@EnableRedisHttpSession // <2>
public class Config {
@Bean
public JedisConnectionFactory connectionFactory() {
return new JedisConnectionFactory(); // <2>
public JedisConnectionFactory connectionFactory(@RedisServerPort int port) {
JedisConnectionFactory connection = new JedisConnectionFactory(); // <3>
connection.setPort(port);
return connection;
}
}
// end::class[]

View File

@@ -18,8 +18,8 @@
<h1>Try it</h1>
<form class="form-inline" role="form" action="./session" method="post">
<label for="attributeName">Attribute Name</label>
<input id="attributeName" type="text" name="attributeName"/>
<label for="attributeValue">Attribute Name</label>
<input id="attributeValue" type="text" name="attributeName"/>
<label for="attributeValue">Attribute Value</label>
<input id="attributeValue" type="text" name="attributeValue"/>
<input type="submit" value="Set Attribute"/>

View File

@@ -8,6 +8,7 @@ sonarRunner {
dependencies {
compile project(':spring-session-data-redis'),
project(':samples:spring-embedded-redis'),
"org.springframework:spring-webmvc:$springVersion",
"org.springframework.security:spring-security-config:$springSecurityVersion",
"org.springframework.security:spring-security-web:$springSecurityVersion",

View File

@@ -15,7 +15,6 @@
*/
package rest;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@@ -25,7 +24,6 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.session.ExpiringSession;
import org.springframework.session.web.http.SessionRepositoryFilter;
import org.springframework.test.context.ContextConfiguration;
@@ -58,29 +56,12 @@ public class RestMockMvcTests {
mvc = MockMvcBuilders.webAppContextSetup(context)
.alwaysDo(print())
.addFilters(sessionRepositoryFilter)
.apply(springSecurity())
.build();
.apply(springSecurity()).build();
}
@Test
public void noSessionOnNoCredentials() throws Exception {
mvc.perform(get("/"))
.andExpect(header().doesNotExist("x-auth-token"))
.andExpect(status().isUnauthorized());
}
@WithMockUser
@Test
public void autheticatedAnnotation() throws Exception {
mvc.perform(get("/"))
.andExpect(content().string("{\"username\":\"user\"}"));
}
@Test
public void autheticatedRequestPostProcessor() throws Exception {
mvc.perform(get("/").with(user("user")))
.andExpect(content().string("{\"username\":\"user\"}"));
.andExpect(header().doesNotExist("x-auth-token"));
}
}

View File

@@ -19,22 +19,27 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.session.redis.embedded.EnableEmbeddedRedis;
import org.springframework.session.redis.embedded.RedisServerPort;
import org.springframework.session.web.http.HeaderHttpSessionStrategy;
import org.springframework.session.web.http.HttpSessionStrategy;
// tag::class[]
@Configuration
@EnableRedisHttpSession // <1>
@EnableEmbeddedRedis // <1>
@EnableRedisHttpSession // <2>
public class HttpSessionConfig {
@Bean
public JedisConnectionFactory connectionFactory() {
return new JedisConnectionFactory(); // <2>
public JedisConnectionFactory connectionFactory(@RedisServerPort int port) {
JedisConnectionFactory factory = new JedisConnectionFactory(); // <3>
factory.setPort(port);
return factory;
}
@Bean
public HttpSessionStrategy httpSessionStrategy() {
return new HeaderHttpSessionStrategy(); // <3>
return new HeaderHttpSessionStrategy(); // <4>
}
}
// end::class[]

View File

@@ -8,6 +8,7 @@ sonarRunner {
dependencies {
compile project(':spring-session-data-redis'),
project(':samples:spring-embedded-redis'),
"org.springframework:spring-web:$springVersion",
"org.springframework.security:spring-security-config:$springSecurityVersion",
"org.springframework.security:spring-security-web:$springSecurityVersion",

View File

@@ -19,15 +19,20 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.session.redis.embedded.EnableEmbeddedRedis;
import org.springframework.session.redis.embedded.RedisServerPort;
// tag::class[]
@Configuration
@EnableRedisHttpSession // <1>
@EnableEmbeddedRedis // <1>
@EnableRedisHttpSession // <2>
public class Config {
@Bean
public JedisConnectionFactory connectionFactory() {
return new JedisConnectionFactory(); // <2>
public JedisConnectionFactory connectionFactory(@RedisServerPort int port) {
JedisConnectionFactory connection = new JedisConnectionFactory(); // <3>
connection.setPort(port);
return connection;
}
}
// end::class[]

View File

@@ -0,0 +1,14 @@
apply from: JAVA_GRADLE
tasks.findByPath("artifactoryPublish")?.enabled = false
sonarRunner {
skipProject = true
}
dependencies {
compile "com.github.kstyrc:embedded-redis:$embeddedRedisVersion",
"org.springframework:spring-context:$springVersion"
testCompile "junit:junit:$junitVersion",
"org.springframework.security:spring-security-test:$springSecurityVersion"
}

View File

@@ -0,0 +1,113 @@
/*
* Copyright 2002-2015 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.session.redis.embedded;
import java.io.IOException;
import java.net.ServerSocket;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertySource;
import redis.embedded.RedisServer;
/**
* Runs an embedded Redis instance. This is only necessary since we do not want
* users to have to setup a Redis instance. In a production environment, this
* would not be used since a Redis Server would be setup.
*
* @author Rob Winch
*/
@Configuration
class EmbeddedRedisConfiguration {
public static final String SERVER_PORT_PROP_NAME = "spring.redis.port";
@Bean
public static RedisServerBean redisServer(ConfigurableEnvironment env) {
RedisServerBean bean = new RedisServerBean();
env.getPropertySources().addLast(bean);
return bean;
}
@Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
/**
* Implements BeanDefinitionRegistryPostProcessor to ensure this Bean is initialized
* before any other Beans. Specifically, we want to ensure that the Redis Server is
* started before RedisHttpSessionConfiguration attempts to enable Keyspace
* notifications. We also want to ensure that we are able to register the
* {@link PropertySource} before any beans are initialized.
*/
static class RedisServerBean extends PropertySource<RedisServerBean> implements InitializingBean, DisposableBean, BeanDefinitionRegistryPostProcessor {
private final int port = getAvailablePort();
private RedisServer redisServer;
public RedisServerBean() {
super("redisServerPortPropertySource");
}
public void afterPropertiesSet() throws Exception {
redisServer = new RedisServer(port);
redisServer.start();
}
public void destroy() throws Exception {
if(redisServer != null) {
redisServer.stop();
}
}
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {}
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {}
@Override
public Object getProperty(String name) {
if(SERVER_PORT_PROP_NAME.equals(name)) {
return port;
}
return null;
}
private static int getAvailablePort() {
ServerSocket socket = null;
try {
socket = new ServerSocket(0);
return socket.getLocalPort();
} catch(IOException e) {
throw new RuntimeException(e);
} finally {
try {
if(socket != null) {
socket.close();
}
}catch(IOException e) {}
}
}
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright 2002-2015 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.session.redis.embedded;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* <p>
* Runs an embedded Redis instance on a random available port.This is only necessary
* sincewe do not want users to have to setup a Redis instance. In a production
* environment, this would not be used since a Redis Server would be setup.
* </p>
* <p>
* The port being used can be identified by using {@literal @RedisServerPort} on a Spring
* Bean. For example:
* </p>
*
* <pre>
* {@literal @Configuration}
* {@literal @EnableEmbeddedRedis}
* public class RedisHttpSessionConfig {
*
* {@literal @Bean}
* public JedisConnectionFactory connectionFactory({@literal @RedisServerPort} int port) throws Exception {
* JedisConnectionFactory connection = new JedisConnectionFactory();
* connection.setPort(port);
* return connection;
* }
*
* }
* </pre>
*
* See <a href="https://github.com/spring-projects/spring-session/issues/121"
* >spring-projects/spring-session/issues/121</a> for details on exposing embedded Redis
* support.
*
* @author Rob Winch
* @see RedisServerPort
*
*/
@Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value={java.lang.annotation.ElementType.TYPE})
@Documented
@Import(EmbeddedRedisConfiguration.class)
@Configuration
public @interface EnableEmbeddedRedis {}

View File

@@ -0,0 +1,50 @@
/*
* Copyright 2002-2015 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.session.redis.embedded;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.beans.factory.annotation.Value;
/**
* A convenience for finding the Redis Server port when using {@link EnableEmbeddedRedis}. For example:
*
* <pre>
* {@literal @Configuration}
* {@literal @EnableEmbeddedRedis}
* public class RedisHttpSessionConfig {
*
* {@literal @Bean}
* public JedisConnectionFactory connectionFactory({@literal @RedisServerPort} int port) throws Exception {
* JedisConnectionFactory connection = new JedisConnectionFactory();
* connection.setPort(port);
* return connection;
* }
*
* }
* </pre>
*
* @author Rob Winch
*/
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Value("${"+EmbeddedRedisConfiguration.SERVER_PORT_PROP_NAME+"}")
public @interface RedisServerPort { }

View File

@@ -8,6 +8,7 @@ sonarRunner {
dependencies {
compile project(':spring-session-data-redis'),
project(':samples:spring-embedded-redis'),
"org.springframework:spring-web:$springVersion",
jstlDependencies

View File

@@ -19,19 +19,24 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.session.redis.embedded.EnableEmbeddedRedis;
import org.springframework.session.redis.embedded.RedisServerPort;
/**
* @author Rob Winch
*/
@EnableEmbeddedRedis
// tag::class[]
@Configuration
@EnableRedisHttpSession
public class Config {
@Bean
public JedisConnectionFactory connectionFactory() {
return new JedisConnectionFactory();
public JedisConnectionFactory connectionFactory(@RedisServerPort int port) {
JedisConnectionFactory connection = new JedisConnectionFactory();
connection.setPort(port);
return connection;
}
}
// end::class[]

View File

@@ -18,6 +18,7 @@ group = 'samples'
dependencies {
compile project(':spring-session-data-redis'),
project(':samples:spring-embedded-redis'),
"org.springframework.boot:spring-boot-starter-web",
"org.springframework.boot:spring-boot-starter-data-jpa",
"org.springframework.boot:spring-boot-starter-thymeleaf",

View File

@@ -22,6 +22,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.session.redis.embedded.RedisServerPort;
@Configuration
public class DataSourceConfig {
@@ -33,7 +34,9 @@ public class DataSourceConfig {
}
@Bean
public JedisConnectionFactory connectionFactory() {
return new JedisConnectionFactory();
public JedisConnectionFactory connectionFactory(@RedisServerPort int port) {
JedisConnectionFactory connection = new JedisConnectionFactory(); // <3>
connection.setPort(port);
return connection;
}
}

View File

@@ -20,6 +20,7 @@ function ApplicationModel(stompClient) {
self.connect = function() {
var headers = {};
var csrf = self.csrfToken();
var headers = {};
headers[csrf.headerName] = csrf.token;
stompClient.connect(headers, function(frame) {

View File

@@ -3,6 +3,7 @@ rootProject.name = 'spring-session-build'
include 'docs'
include 'samples:boot'
include 'samples:spring-embedded-redis'
include 'samples:hazelcast'
include 'samples:httpsession'
include 'samples:httpsession-xml'

View File

@@ -10,12 +10,6 @@ dependencies {
"org.springframework.data:spring-data-redis:$springDataRedisVersion",
"redis.clients:jedis:$jedisVersion",
"org.apache.commons:commons-pool2:$commonsPoolVersion"
}
dependencyManagement {
springIoTestRuntime {
imports {
mavenBom "io.spring.platform:platform-bom:${springIoVersion}"
}
}
springIoVersions "io.spring.platform:platform-versions:${springIoVersion}@properties"
}

View File

@@ -1,5 +1,4 @@
apply from: JAVA_GRADLE
apply from: SPRING3_GRADLE
apply from: MAVEN_GRADLE
apply plugin: 'spring-io'
@@ -21,7 +20,8 @@ dependencies {
"org.springframework:spring-messaging:$springVersion",
"org.springframework:spring-websocket:$springVersion"
provided "javax.servlet:javax.servlet-api:$servletApiVersion"
integrationTestCompile "redis.clients:jedis:2.4.1",
integrationTestCompile project(':samples:spring-embedded-redis'),
"redis.clients:jedis:2.4.1",
"org.apache.commons:commons-pool2:2.2"
testCompile "junit:junit:$junitVersion",
@@ -32,14 +32,7 @@ dependencies {
jacoco "org.jacoco:org.jacoco.agent:0.7.2.201409121644:runtime"
}
dependencyManagement {
springIoTestRuntime {
imports {
mavenBom "io.spring.platform:platform-bom:${springIoVersion}"
}
}
springIoVersions "io.spring.platform:platform-versions:${springIoVersion}@properties"
}
ext.javadocLinks = [

View File

@@ -34,6 +34,8 @@ import org.springframework.session.Session;
import org.springframework.session.SessionRepository;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.session.events.SessionDestroyedEvent;
import org.springframework.session.redis.embedded.EnableEmbeddedRedis;
import org.springframework.session.redis.embedded.RedisServerPort;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
@@ -122,10 +124,12 @@ public class RedisOperationsSessionRepositoryITests<S extends Session> {
@Configuration
@EnableRedisHttpSession
@EnableEmbeddedRedis
static class Config {
@Bean
public JedisConnectionFactory connectionFactory() throws Exception {
public JedisConnectionFactory connectionFactory(@RedisServerPort int port) throws Exception {
JedisConnectionFactory factory = new JedisConnectionFactory();
factory.setPort(port);
factory.setUsePool(false);
return factory;
}

View File

@@ -34,6 +34,8 @@ import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.session.ExpiringSession;
import org.springframework.session.SessionRepository;
import org.springframework.session.events.SessionDestroyedEvent;
import org.springframework.session.redis.embedded.EnableEmbeddedRedis;
import org.springframework.session.redis.embedded.RedisServerPort;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
@@ -105,10 +107,12 @@ public class EnableRedisHttpSessionExpireSessionDestroyedTests<S extends Expirin
@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1)
@EnableEmbeddedRedis
static class Config {
@Bean
public JedisConnectionFactory connectionFactory() throws Exception {
public JedisConnectionFactory connectionFactory(@RedisServerPort int port) throws Exception {
JedisConnectionFactory factory = new JedisConnectionFactory();
factory.setPort(port);
factory.setUsePool(false);
return factory;
}

View File

@@ -125,12 +125,12 @@ public class RedisHttpSessionConfiguration implements ImportAware, BeanClassLoad
// search parent classes
Class<?> currentClass = ClassUtils.resolveClassName(importMetadata.getClassName(), beanClassLoader);
for(Class<?> classToInspect = currentClass ;classToInspect != null; classToInspect = classToInspect.getSuperclass()) {
EnableRedisHttpSession enableRedisHttpSessionAnnotation = AnnotationUtils.findAnnotation(classToInspect, EnableRedisHttpSession.class);
if(enableRedisHttpSessionAnnotation == null) {
EnableRedisHttpSession enableWebSecurityAnnotation = AnnotationUtils.findAnnotation(classToInspect, EnableRedisHttpSession.class);
if(enableWebSecurityAnnotation == null) {
continue;
}
enableAttrMap = AnnotationUtils
.getAnnotationAttributes(enableRedisHttpSessionAnnotation);
.getAnnotationAttributes(enableWebSecurityAnnotation);
enableAttrs = AnnotationAttributes.fromMap(enableAttrMap);
}
}
@@ -143,7 +143,7 @@ public class RedisHttpSessionConfiguration implements ImportAware, BeanClassLoad
}
@Bean
public InitializingBean enableRedisKeyspaceNotificationsInitializer(RedisConnectionFactory connectionFactory) {
public EnableRedisKeyspaceNotificationsInitializer enableRedisKeyspaceNotificationsInitializer(RedisConnectionFactory connectionFactory) {
return new EnableRedisKeyspaceNotificationsInitializer(connectionFactory, configureRedisAction);
}
@@ -153,6 +153,8 @@ public class RedisHttpSessionConfiguration implements ImportAware, BeanClassLoad
* cleaned up properly. For example, the mapping of the Session to WebSocket connections may not get cleaned up.
*/
static class EnableRedisKeyspaceNotificationsInitializer implements InitializingBean {
static final String CONFIG_NOTIFY_KEYSPACE_EVENTS = "notify-keyspace-events";
private final RedisConnectionFactory connectionFactory;
private ConfigureRedisAction configure;

View File

@@ -17,7 +17,6 @@ package org.springframework.session.web.http;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
@@ -153,8 +152,6 @@ import org.springframework.session.Session;
* @author Rob Winch
*/
public final class CookieHttpSessionStrategy implements MultiHttpSessionStrategy, HttpSessionManager {
private static final String SESSION_IDS_WRITTEN_ATTR = CookieHttpSessionStrategy.class.getName().concat(".SESSIONS_WRITTEN_ATTR");
static final String DEFAULT_ALIAS = "0";
static final String DEFAULT_SESSION_ALIAS_PARAM_NAME = "_s";
@@ -211,12 +208,6 @@ public final class CookieHttpSessionStrategy implements MultiHttpSessionStrategy
}
public void onNewSession(Session session, HttpServletRequest request, HttpServletResponse response) {
Set<String> sessionIdsWritten = getSessionIdsWritten(request);
if(sessionIdsWritten.contains(session.getId())) {
return;
}
sessionIdsWritten.add(session.getId());
Map<String,String> sessionIds = getSessionIds(request);
String sessionAlias = getCurrentSessionAlias(request);
sessionIds.put(sessionAlias, session.getId());
@@ -224,16 +215,6 @@ public final class CookieHttpSessionStrategy implements MultiHttpSessionStrategy
response.addCookie(sessionCookie);
}
@SuppressWarnings("unchecked")
private Set<String> getSessionIdsWritten(HttpServletRequest request) {
Set<String> sessionsWritten = (Set<String>) request.getAttribute(SESSION_IDS_WRITTEN_ATTR);
if(sessionsWritten == null) {
sessionsWritten = new HashSet<String>();
request.setAttribute(SESSION_IDS_WRITTEN_ATTR, sessionsWritten);
}
return sessionsWritten;
}
private Cookie createSessionCookie(HttpServletRequest request,
Map<String, String> sessionIds) {
Cookie sessionCookie = new Cookie(cookieName,"");

View File

@@ -55,15 +55,9 @@ import org.springframework.session.SessionRepository;
* <li>The client is notified that the session id is no longer valid with {@link HttpSessionStrategy#onInvalidateSession(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}</li>
* </ul>
*
* <p>
* The SessionRepositoryFilter must be placed before any Filter that access the HttpSession or that might commit the response
* to ensure the session is overridden and persisted properly.
* </p>
*
* @since 1.0
* @author Rob Winch
*/
@SuppressWarnings("deprecation")
@Order(SessionRepositoryFilter.DEFAULT_ORDER)
public class SessionRepositoryFilter<S extends ExpiringSession> extends OncePerRequestFilter {
public static final String SESSION_REPOSITORY_ATTR = SessionRepository.class.getName();
@@ -83,7 +77,7 @@ public class SessionRepositoryFilter<S extends ExpiringSession> extends OncePerR
*/
public SessionRepositoryFilter(SessionRepository<S> sessionRepository) {
if(sessionRepository == null) {
throw new IllegalArgumentException("sessionRepository cannot be null");
throw new IllegalArgumentException("SessionRepository cannot be null");
}
this.sessionRepository = sessionRepository;
}
@@ -94,8 +88,8 @@ public class SessionRepositoryFilter<S extends ExpiringSession> extends OncePerR
* @param httpSessionStrategy the {@link HttpSessionStrategy} to use. Cannot be null.
*/
public void setHttpSessionStrategy(HttpSessionStrategy httpSessionStrategy) {
if(httpSessionStrategy == null) {
throw new IllegalArgumentException("httpSessionStrategy cannot be null");
if(sessionRepository == null) {
throw new IllegalArgumentException("httpSessionIdStrategy cannot be null");
}
this.httpSessionStrategy = new MultiHttpSessionStrategyAdapter(httpSessionStrategy);
}
@@ -106,8 +100,8 @@ public class SessionRepositoryFilter<S extends ExpiringSession> extends OncePerR
* @param httpSessionStrategy the {@link MultiHttpSessionStrategy} to use. Cannot be null.
*/
public void setHttpSessionStrategy(MultiHttpSessionStrategy httpSessionStrategy) {
if(httpSessionStrategy == null) {
throw new IllegalArgumentException("httpSessionStrategy cannot be null");
if(sessionRepository == null) {
throw new IllegalArgumentException("httpSessionIdStrategy cannot be null");
}
this.httpSessionStrategy = httpSessionStrategy;
}
@@ -167,7 +161,7 @@ public class SessionRepositoryFilter<S extends ExpiringSession> extends OncePerR
* @since 1.0
*/
private final class SessionRepositoryRequestWrapper extends HttpServletRequestWrapper {
private final String CURRENT_SESSION_ATTR = HttpServletRequestWrapper.class.getName();
private HttpSessionWrapper currentSession;
private Boolean requestedSessionIdValid;
private boolean requestedSessionInvalidated;
private final HttpServletResponse response;
@@ -183,7 +177,7 @@ public class SessionRepositoryFilter<S extends ExpiringSession> extends OncePerR
* Uses the HttpSessionStrategy to write the session id tot he response and persist the Session.
*/
private void commitSession() {
HttpSessionWrapper wrappedSession = getCurrentSession();
HttpSessionWrapper wrappedSession = currentSession;
if(wrappedSession == null) {
if(isInvalidateClientSession()) {
httpSessionStrategy.onInvalidateSession(this, response);
@@ -197,20 +191,7 @@ public class SessionRepositoryFilter<S extends ExpiringSession> extends OncePerR
}
}
@SuppressWarnings("unchecked")
private HttpSessionWrapper getCurrentSession() {
return (HttpSessionWrapper) getAttribute(CURRENT_SESSION_ATTR);
}
private void setCurrentSession(HttpSessionWrapper currentSession) {
if(currentSession == null) {
removeAttribute(CURRENT_SESSION_ATTR);
} else {
setAttribute(CURRENT_SESSION_ATTR, currentSession);
}
}
@SuppressWarnings({ "unused", "unchecked" })
@SuppressWarnings("unused")
public String changeSessionId() {
HttpSession session = getSession(false);
@@ -229,12 +210,9 @@ public class SessionRepositoryFilter<S extends ExpiringSession> extends OncePerR
}
sessionRepository.delete(session.getId());
HttpSessionWrapper original = getCurrentSession();
setCurrentSession(null);
currentSession = null;
HttpSession newSession = getSession();
original.session = ((HttpSessionWrapper)newSession).session;
newSession.setMaxInactiveInterval(session.getMaxInactiveInterval());
for(Map.Entry<String, Object> attr : attrs.entrySet()) {
String attrName = attr.getKey();
@@ -262,12 +240,11 @@ public class SessionRepositoryFilter<S extends ExpiringSession> extends OncePerR
}
private boolean isInvalidateClientSession() {
return getCurrentSession() == null && requestedSessionInvalidated;
return currentSession == null && requestedSessionInvalidated;
}
@Override
public HttpSession getSession(boolean create) {
HttpSessionWrapper currentSession = getCurrentSession();
if(currentSession != null) {
return currentSession;
}
@@ -278,7 +255,6 @@ public class SessionRepositoryFilter<S extends ExpiringSession> extends OncePerR
this.requestedSessionIdValid = true;
currentSession = new HttpSessionWrapper(session, getServletContext());
currentSession.setNew(false);
setCurrentSession(currentSession);
return currentSession;
}
}
@@ -287,7 +263,6 @@ public class SessionRepositoryFilter<S extends ExpiringSession> extends OncePerR
}
S session = sessionRepository.createSession();
currentSession = new HttpSessionWrapper(session, getServletContext());
setCurrentSession(currentSession);
return currentSession;
}
@@ -316,7 +291,7 @@ public class SessionRepositoryFilter<S extends ExpiringSession> extends OncePerR
* @since 1.0
*/
private final class HttpSessionWrapper implements HttpSession {
private S session;
private final S session;
private final ServletContext servletContext;
private boolean invalidated;
private boolean old;
@@ -399,7 +374,7 @@ public class SessionRepositoryFilter<S extends ExpiringSession> extends OncePerR
checkState();
this.invalidated = true;
requestedSessionInvalidated = true;
setCurrentSession(null);
currentSession = null;
sessionRepository.delete(getId());
}

View File

@@ -1,78 +0,0 @@
/*
* Copyright 2002-2015 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.session.data.redis.config.annotation.web.http.gh109;
import static org.mockito.Mockito.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.session.ExpiringSession;
import org.springframework.session.data.redis.RedisOperationsSessionRepository;
import org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
/**
* This test must be in a different package than RedisHttpSessionConfiguration.
*
* @author Rob Winch
* @since 1.0.2
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@WebAppConfiguration
public class Gh109Tests {
@Test
public void loads() {
}
@Configuration
static class Config extends RedisHttpSessionConfiguration {
int sessionTimeout = 100;
/**
* override sessionRepository construction to set the custom
* session-timeout
*/
@Bean
@Override
public RedisOperationsSessionRepository sessionRepository(
RedisTemplate<String, ExpiringSession> sessionRedisTemplate) {
RedisOperationsSessionRepository sessionRepository = new RedisOperationsSessionRepository(
sessionRedisTemplate);
sessionRepository.setDefaultMaxInactiveInterval(sessionTimeout);
return sessionRepository;
}
@Bean
public RedisConnectionFactory redisConnectionFactory() {
RedisConnectionFactory factory = mock(RedisConnectionFactory.class);
RedisConnection connection = mock(RedisConnection.class);
when(factory.getConnection()).thenReturn(connection);
return factory;
}
}
}

View File

@@ -68,28 +68,6 @@ public class CookieHttpSessionStrategyTests {
assertThat(getSessionId()).isEqualTo(session.getId());
}
@Test
public void onNewSessionTwiceSameId() throws Exception {
strategy.onNewSession(session, request, response);
strategy.onNewSession(session, request, response);
assertThat(response.getCookies()).hasSize(1);
}
@Test
public void onNewSessionTwiceNewId() throws Exception {
Session newSession = new MapSession();
strategy.onNewSession(session, request, response);
strategy.onNewSession(newSession, request, response);
Cookie[] cookies = response.getCookies();
assertThat(cookies).hasSize(2);
assertThat(cookies[0].getValue()).isEqualTo(session.getId());
assertThat(cookies[1].getValue()).isEqualTo(newSession.getId());
}
@Test
public void onNewSessionExistingSessionSameAlias() throws Exception {
Session existing = new MapSession();

View File

@@ -19,6 +19,7 @@ import static org.fest.assertions.Assertions.assertThat;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
@@ -50,7 +51,7 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.annotation.OrderUtils;
import org.springframework.mock.web.MockFilterChain;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
@@ -63,12 +64,10 @@ import org.springframework.test.util.ReflectionTestUtils;
@RunWith(MockitoJUnitRunner.class)
@SuppressWarnings("deprecation")
public class SessionRepositoryFilterTests {
public class SessionRepositoryFilterTests<S extends ExpiringSession> {
@Mock
private HttpSessionStrategy strategy;
private Map<String, ExpiringSession> sessions;
private SessionRepository<ExpiringSession> sessionRepository;
private SessionRepositoryFilter<ExpiringSession> filter;
@@ -81,8 +80,7 @@ public class SessionRepositoryFilterTests {
@Before
public void setup() throws Exception {
sessions = new HashMap<String, ExpiringSession>();
sessionRepository = new MapSessionRepository(sessions);
sessionRepository = new MapSessionRepository();
filter = new SessionRepositoryFilter<ExpiringSession>(sessionRepository);
setupRequest();
}
@@ -176,7 +174,6 @@ public class SessionRepositoryFilterTests {
});
final String id = (String) request.getAttribute(ID_ATTR);
setupRequest();
doFilter(new DoInFilter() {
@Override
@@ -476,13 +473,7 @@ public class SessionRepositoryFilterTests {
doFilter(new DoInFilter() {
@Override
public void doFilter(HttpServletRequest wrappedRequest) {
HttpSession originalSession = wrappedRequest.getSession();
assertThat(originalSession.getId()).isEqualTo(originalSessionId);
String changeSessionId = ReflectionTestUtils.invokeMethod(wrappedRequest, "changeSessionId");
assertThat(changeSessionId).isNotEqualTo(originalSessionId);
// gh-227
assertThat(originalSession.getId()).isEqualTo(changeSessionId);
ReflectionTestUtils.invokeMethod(wrappedRequest, "changeSessionId");
}
});
@@ -561,28 +552,6 @@ public class SessionRepositoryFilterTests {
});
}
// gh-229
@Test
public void doFilterGetSessionGetSessionOnError() throws Exception {
doFilter(new DoInFilter() {
@Override
public void doFilter(HttpServletRequest wrappedRequest) {
wrappedRequest.getSession().setAttribute("a", "b");
}
});
// reuse the same request similar to processing an ERROR dispatch
doFilter(new DoInFilter() {
@Override
public void doFilter(HttpServletRequest wrappedRequest) {
assertThat(wrappedRequest.getSession(false)).isNotNull();
}
});
assertThat(this.sessions.size()).isEqualTo(1);
}
@Test
public void doFilterCookieSecuritySettings() throws Exception {
request.setSecure(true);
@@ -1102,7 +1071,6 @@ public class SessionRepositoryFilterTests {
HttpServletRequest request = (HttpServletRequest) chain.getRequest();
String id = request.getSession().getId();
when(strategy.getRequestedSessionId(any(HttpServletRequest.class))).thenReturn(id);
setupRequest();
doFilter(new DoInFilter(){
@Override
@@ -1169,7 +1137,7 @@ public class SessionRepositoryFilterTests {
@Test
public void order() {
assertThat(AnnotationAwareOrderComparator.INSTANCE.compare(filter, new SessionRepositoryFilterDefaultOrder()));
assertThat(OrderUtils.getOrder(filter.getClass())).isEqualTo(SessionRepositoryFilter.DEFAULT_ORDER);
}
// We want the filter to work without any dependencies on Spring
@@ -1179,16 +1147,6 @@ public class SessionRepositoryFilterTests {
Ordered o = (Ordered) filter;
}
@Test(expected = IllegalArgumentException.class)
public void setHttpSessionStrategyNull() {
filter.setHttpSessionStrategy((HttpSessionStrategy) null);
}
@Test(expected = IllegalArgumentException.class)
public void setMultiHttpSessionStrategyNull() {
filter.setHttpSessionStrategy((MultiHttpSessionStrategy) null);
}
// --- helper methods
private void assertNewSession() {
@@ -1257,10 +1215,4 @@ public class SessionRepositoryFilterTests {
}
void doFilter(HttpServletRequest wrappedRequest) {}
}
static class SessionRepositoryFilterDefaultOrder implements Ordered {
public int getOrder() {
return SessionRepositoryFilter.DEFAULT_ORDER;
}
}
}