Compare commits

..

50 Commits

Author SHA1 Message Date
Eleftheria Stein
478160e5b2 Add End-of-Life Notice 2021-07-19 12:22:21 +02:00
Eleftheria Stein
2ef91fa7a2 Remove from CI 2021-07-19 12:21:31 +02:00
Eleftheria Stein
8cd185db6b Update Deploy Docs host
The build conventions plugin does not support a property, so we must
override the configuration for docs.host to docs-ip.spring.io

Closes gh-1845
2021-04-28 17:58:00 +02:00
Eleftheria Stein
6fbd11e893 Update Deploy Docs host
Closes gh-1845
2021-04-28 14:42:36 +02:00
Eleftheria Stein
401bff267c Upgrade test dependencies 2021-04-28 14:22:29 +02:00
Eleftheria Stein
7805aff531 Next development version 2021-04-13 16:24:52 +02:00
Eleftheria Stein
7d5ba54289 Release 2.2.6.RELEASE 2021-04-13 15:59:32 +02:00
Eleftheria Stein
45e6c3a0ba Upgrade test dependencies 2021-04-13 15:14:43 +02:00
Eleftheria Stein
9f142ed49d Upgrade Spring Data to Moore-SR13
Closes gh-1839
2021-04-13 15:14:11 +02:00
Eleftheria Stein
0758dd737d Upgrade Spring Security to 5.2.10.RELEASE
Closes gh-1838
2021-04-13 15:13:30 +02:00
Eleftheria Stein
f7852f379a Upgrade Spring Framework to 5.2.14.RELEASE
Closes gh-1836
2021-04-13 15:13:03 +02:00
Eleftheria Stein
61d3d56e6d Upgrade Hazelcast to 3.12.12
Closes gh-1837
2021-04-13 15:12:08 +02:00
Eleftheria Stein
7d929457e4 Upgrade Reactor to Dysprosium-SR19
Closes gh-1835
2021-04-13 15:11:43 +02:00
Eleftheria Stein
3d266960ba Upgrade samples to Spring Boot 2.2.13.RELEASE
Closes gh-1840
2021-04-13 15:11:08 +02:00
Eleftheria Stein
4d96099e03 Throw exception if session created after response
Closes gh-1798
2021-03-25 13:01:09 +02:00
Eleftheria Stein
e0103f62d6 Update to spring-build-conventions:0.0.27.1.RELEASE
Fixes use of repo.spring.io
2021-01-28 18:14:51 +01:00
Eleftheria Stein
304b496caf Next development version 2021-01-19 17:48:59 +01:00
Eleftheria Stein
c1e3c2831d Release 2.2.5.RELEASE 2021-01-19 15:08:24 +01:00
Eleftheria Stein
e228279683 Upgrade Hazelcast to 3.12.11
Closes gh-1776
2021-01-18 16:28:54 +01:00
Eleftheria Stein
70c14368e5 Upgrade Spring Data to Moore-SR12
Closes gh-1775
2021-01-18 16:27:19 +01:00
Eleftheria Stein
7f9abc822f Upgrade Spring Security to 5.2.8
Closes gh-1774
2021-01-18 16:26:04 +01:00
Eleftheria Stein
f426f91574 Upgrade Spring Framework to 5.2.12
Closes gh-1773
2021-01-18 16:16:00 +01:00
Eleftheria Stein
316fe09f72 Upgrade Reactor to Dysprosium-SR16
Closes gh-1772
2021-01-18 15:46:38 +01:00
Eleftheria Stein
00338e23dd Update testcontainers to fix Docker connectivity
Closes gh-1751
2021-01-07 11:26:59 +01:00
Eleftheria Stein
c6c2d53204 Add artifactory credentials to build 2020-11-18 13:34:35 +01:00
Eleftheria Stein
bf5dcda905 Next development version 2020-09-16 16:37:49 +02:00
Eleftheria Stein
32ec8b2b28 Release 2.2.4.RELEASE 2020-09-16 12:32:33 +02:00
Eleftheria Stein
3268d1f790 Upgrade Spring Data to Moore-SR10
Closes gh-1701
2020-09-16 12:13:33 +02:00
Eleftheria Stein
380a1e81ac Upgrade test dependencies 2020-09-15 11:53:08 +02:00
Eleftheria Stein
5be4141103 Upgrade Spring Security to 5.2.6.RELEASE
Closes gh-1693
2020-09-15 11:51:36 +02:00
Eleftheria Stein
4ebf18dc4e Upgrade Spring Framework to 5.2.9.RELEASE
Closes gh-1692
2020-09-15 11:51:15 +02:00
Eleftheria Stein
b5c67736ad Upgrade Reactor to Dysprosium-SR12
Closes gh-1691
2020-09-15 11:50:23 +02:00
Eleftheria Stein
dfab409f30 Upgrade samples to Spring Boot 2.2.9.RELEASE
Closes gh-1690
2020-09-15 11:49:32 +02:00
Eleftheria Stein
a0a394d17f Remove JDK 9 and 10 from Jenkins build
Closes gh-1659
2020-07-16 15:53:36 +02:00
Eleftheria Stein
1a98f25fdb Next development version 2020-05-12 17:48:30 -04:00
Eleftheria Stein
1afb5d5a17 Release 2.2.3.RELEASE 2020-05-12 16:56:14 -04:00
Eleftheria Stein
365a244a9b Upgrade Spring Security to 5.2.4.RELEASE
Resolves gh-1634
2020-05-12 16:30:27 -04:00
Eleftheria Stein
0b4140d892 Upgrade Spring Data to Moore-SR7
Resolves gh-1633
2020-05-12 16:29:48 -04:00
Eleftheria Stein
78a85789c9 Upgrade Spring Framework to 5.2.6.RELEASE
Resolves gh-1632
2020-05-12 16:29:24 -04:00
Eleftheria Stein
59350ed559 Upgrade Reactor to Dysprosium-SR7
Resolves: gh-1631
2020-05-12 16:28:45 -04:00
Eleftheria Stein
811e156a9c Upgrade samples to Spring Boot 2.2.7
Resolves gh-1630
2020-05-12 16:28:08 -04:00
Eleftheria Stein
05a9903348 Upgrade test dependencies 2020-05-12 16:17:13 -04:00
Rob Winch
d8ae336b24 Find by Username Sample switch from DELETE to POST
Spring Boot 2.2 no longer adds HiddenHttpMethodFilter by default See
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.2-Release-Notes#httphiddenmethodfilter-disabled-by-default
This means that trying to map DELETE requests using _method variable
does not work.

This changes the mapping to use a POST which doesn't require the
HiddenHttpMethodFilter which might expose the application to unnecessary
security risk by allowing the HTTP method to be overridden.

Closes gh-1613
2020-04-13 09:44:15 -05:00
Eleftheria Stein
315112f2a2 Next Development Build 2020-03-04 16:43:52 -05:00
Eleftheria Stein
e859da6d27 Release 2.2.2.RELEASE 2020-03-04 16:03:14 -05:00
Eleftheria Stein
028bae1f11 Upgrade samples to Spring Boot 2.2.5
Resolves #1596
2020-03-04 10:50:54 -05:00
Eleftheria Stein
234cb6dd88 Upgrade Spring Security to 5.2.2.RELEASE
Resolves #1595
2020-03-04 10:50:05 -05:00
Eleftheria Stein
43101308ec Upgrade Spring Data to Moore-SR5
Resolves #1594
2020-03-04 10:49:17 -05:00
Eleftheria Stein
089f6b92de Upgrade Spring Framework to 5.2.4.RELEASE
Resolves #1593
2020-03-04 10:48:41 -05:00
Eleftheria Stein
c6d129a5a5 Upgrade Reactor to Dysprosium-SR5
Resolves #1592
2020-03-04 10:42:02 -05:00
44 changed files with 169 additions and 356 deletions

181
Jenkinsfile vendored
View File

@@ -1,181 +0,0 @@
properties([
buildDiscarder(logRotator(numToKeepStr: '10')),
pipelineTriggers([
cron('@daily')
]),
])
def SUCCESS = hudson.model.Result.SUCCESS.toString()
currentBuild.result = SUCCESS
try {
parallel check: {
stage('Check') {
timeout(time: 45, unit: 'MINUTES') {
node('linux') {
label 'spring-session'
checkout scm
sh "git clean -dfx"
try {
withEnv(["JAVA_HOME=${tool 'jdk8'}"]) {
sh './gradlew clean check --no-daemon --stacktrace'
}
}
catch (e) {
currentBuild.result = 'FAILED: check'
throw e
}
finally {
junit '**/build/test-results/*/*.xml'
}
}
}
}
},
jdk9: {
stage('JDK 9') {
timeout(time: 45, unit: 'MINUTES') {
node('linux') {
checkout scm
sh "git clean -dfx"
try {
withEnv(["JAVA_HOME=${tool 'jdk9'}"]) {
sh './gradlew clean test --no-daemon --stacktrace'
}
}
catch (e) {
currentBuild.result = 'FAILED: jdk9'
throw e
}
}
}
}
},
jdk10: {
stage('JDK 10') {
timeout(time: 45, unit: 'MINUTES') {
node('linux') {
checkout scm
sh "git clean -dfx"
try {
withEnv(["JAVA_HOME=${tool 'jdk10'}"]) {
sh './gradlew clean test --no-daemon --stacktrace'
}
}
catch (e) {
currentBuild.result = 'FAILED: jdk10'
throw e
}
}
}
}
},
jdk11: {
stage('JDK 11') {
timeout(time: 45, unit: 'MINUTES') {
node('linux') {
checkout scm
sh "git clean -dfx"
try {
withEnv(["JAVA_HOME=${tool 'jdk11'}"]) {
sh './gradlew clean test integrationTest --no-daemon --stacktrace'
}
}
catch (e) {
currentBuild.result = 'FAILED: jdk11'
throw e
}
}
}
}
},
jdk12: {
stage('JDK 12') {
timeout(time: 45, unit: 'MINUTES') {
node('linux') {
checkout scm
try {
withEnv(["JAVA_HOME=${tool 'openjdk12'}"]) {
sh './gradlew clean test integrationTest --no-daemon --stacktrace'
}
}
catch (e) {
currentBuild.result = 'FAILED: jdk12'
throw e
}
}
}
}
}
if (currentBuild.result == 'SUCCESS') {
parallel artifacts: {
stage('Deploy Artifacts') {
node('linux') {
checkout scm
sh "git clean -dfx"
try {
withCredentials([file(credentialsId: 'spring-signing-secring.gpg', variable: 'SIGNING_KEYRING_FILE')]) {
withCredentials([string(credentialsId: 'spring-gpg-passphrase', variable: 'SIGNING_PASSWORD')]) {
withCredentials([usernamePassword(credentialsId: 'oss-token', passwordVariable: 'OSSRH_PASSWORD', usernameVariable: 'OSSRH_USERNAME')]) {
withCredentials([usernamePassword(credentialsId: '02bd1690-b54f-4c9f-819d-a77cb7a9822c', usernameVariable: 'ARTIFACTORY_USERNAME', passwordVariable: 'ARTIFACTORY_PASSWORD')]) {
withEnv(["JAVA_HOME=${tool 'jdk8'}"]) {
sh './gradlew deployArtifacts --no-daemon --stacktrace -Psigning.secretKeyRingFile=$SIGNING_KEYRING_FILE -Psigning.keyId=$SPRING_SIGNING_KEYID -Psigning.password=$SIGNING_PASSWORD -PossrhUsername=$OSSRH_USERNAME -PossrhPassword=$OSSRH_PASSWORD -PartifactoryUsername=$ARTIFACTORY_USERNAME -PartifactoryPassword=$ARTIFACTORY_PASSWORD'
sh './gradlew finalizeDeployArtifacts --no-daemon --stacktrace -Psigning.secretKeyRingFile=$SIGNING_KEYRING_FILE -Psigning.keyId=$SPRING_SIGNING_KEYID -Psigning.password=$SIGNING_PASSWORD -PossrhUsername=$OSSRH_USERNAME -PossrhPassword=$OSSRH_PASSWORD -PartifactoryUsername=$ARTIFACTORY_USERNAME -PartifactoryPassword=$ARTIFACTORY_PASSWORD'
}
}
}
}
}
}
catch (e) {
currentBuild.result = 'FAILED: artifacts'
throw e
}
}
}
},
docs: {
stage('Deploy Docs') {
node('linux') {
checkout scm
sh "git clean -dfx"
try {
withCredentials([file(credentialsId: 'docs.spring.io-jenkins_private_ssh_key', variable: 'DEPLOY_SSH_KEY')]) {
withEnv(["JAVA_HOME=${tool 'jdk8'}"]) {
sh './gradlew deployDocs --no-daemon --stacktrace -PdeployDocsSshKeyPath=$DEPLOY_SSH_KEY -PdeployDocsSshUsername=$SPRING_DOCS_USERNAME'
}
}
}
catch (e) {
currentBuild.result = 'FAILED: docs'
throw e
}
}
}
}
}
}
finally {
def buildStatus = currentBuild.result
def buildNotSuccess = !SUCCESS.equals(buildStatus)
def lastBuildNotSuccess = !SUCCESS.equals(currentBuild.previousBuild?.result)
if (buildNotSuccess || lastBuildNotSuccess) {
stage('Notify') {
node {
final def RECIPIENTS = [[$class: 'DevelopersRecipientProvider'], [$class: 'RequesterRecipientProvider']]
def subject = "${buildStatus}: Build ${env.JOB_NAME} ${env.BUILD_NUMBER} status is now ${buildStatus}"
def details = "The build status changed to ${buildStatus}. For details see ${env.BUILD_URL}"
emailext(
subject: subject,
body: details,
recipientProviders: RECIPIENTS,
to: "$SPRING_SESSION_TEAM_EMAILS"
)
}
}
}
}

View File

@@ -1,3 +1,9 @@
[NOTE]
======
This branch of Spring Session has reached its https://github.com/spring-projects/spring-boot/wiki/Supported-Versions[End of Life], meaning that there are no further maintenance releases or security patches planned.
Please migrate to a supported branch as soon as possible.
======
= Spring Session
image:https://travis-ci.org/spring-projects/spring-session.svg?branch=master["Build Status", link="https://travis-ci.org/spring-projects/spring-session"] image:https://badges.gitter.im/spring-projects/spring-session.svg[link="https://gitter.im/spring-projects/spring-session?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"]

View File

@@ -4,7 +4,7 @@ buildscript {
snapshotBuild = version.endsWith('SNAPSHOT')
milestoneBuild = !(releaseBuild || snapshotBuild)
springBootVersion = '2.2.5.RELEASE'
springBootVersion = '2.2.13.RELEASE'
}
repositories {
@@ -13,7 +13,7 @@ buildscript {
}
dependencies {
classpath 'io.spring.gradle:spring-build-conventions:0.0.28.RELEASE'
classpath 'io.spring.gradle:spring-build-conventions:0.0.27.1.RELEASE'
classpath "org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion"
}
}
@@ -34,3 +34,19 @@ subprojects {
useJUnitPlatform()
}
}
if (project.hasProperty('artifactoryUsername')) {
allprojects { project ->
project.repositories { repos ->
all { repo ->
if (!repo.url.toString().startsWith("https://repo.spring.io/")) {
return;
}
repo.credentials {
username = artifactoryUsername
password = artifactoryPassword
}
}
}
}
}

View File

@@ -1,3 +1,3 @@
org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
org.gradle.parallel=true
version=2.3.0.RC1
version=2.2.7.BUILD-SNAPSHOT

View File

@@ -1,15 +1,15 @@
dependencyManagement {
imports {
mavenBom 'io.projectreactor:reactor-bom:Dysprosium-SR5'
mavenBom 'org.junit:junit-bom:5.6.0'
mavenBom 'org.springframework:spring-framework-bom:5.2.4.RELEASE'
mavenBom 'org.springframework.data:spring-data-releasetrain:Neumann-M3'
mavenBom 'org.springframework.security:spring-security-bom:5.3.0.RC1'
mavenBom 'org.testcontainers:testcontainers-bom:1.12.2'
mavenBom 'io.projectreactor:reactor-bom:Dysprosium-SR19'
mavenBom 'org.junit:junit-bom:5.5.2'
mavenBom 'org.springframework:spring-framework-bom:5.2.14.RELEASE'
mavenBom 'org.springframework.data:spring-data-releasetrain:Moore-SR13'
mavenBom 'org.springframework.security:spring-security-bom:5.2.10.RELEASE'
mavenBom 'org.testcontainers:testcontainers-bom:1.15.3'
}
dependencies {
dependencySet(group: 'com.hazelcast', version: '3.12.6') {
dependencySet(group: 'com.hazelcast', version: '3.12.12') {
entry 'hazelcast'
entry 'hazelcast-client'
}
@@ -18,18 +18,18 @@ dependencyManagement {
dependency 'com.ibm.db2:jcc:11.5.0.0'
dependency 'com.microsoft.sqlserver:mssql-jdbc:7.4.1.jre8'
dependency 'com.oracle.ojdbc:ojdbc8:19.3.0.0'
dependency 'com.zaxxer:HikariCP:3.4.1'
dependency 'com.zaxxer:HikariCP:3.4.5'
dependency 'edu.umd.cs.mtc:multithreadedtc:1.01'
dependency 'io.lettuce:lettuce-core:5.2.2.RELEASE'
dependency 'javax.annotation:javax.annotation-api:1.3.2'
dependency 'javax.servlet:javax.servlet-api:4.0.1'
dependency 'junit:junit:4.13'
dependency 'mysql:mysql-connector-java:8.0.19'
dependency 'junit:junit:4.12'
dependency 'mysql:mysql-connector-java:8.0.23'
dependency 'org.apache.derby:derby:10.14.2.0'
dependency 'org.assertj:assertj-core:3.15.0'
dependency 'org.hsqldb:hsqldb:2.5.0'
dependency 'org.assertj:assertj-core:3.13.2'
dependency 'org.hsqldb:hsqldb:2.5.1'
dependency 'org.mariadb.jdbc:mariadb-java-client:2.4.4'
dependency 'org.mockito:mockito-core:3.3.0'
dependency 'org.postgresql:postgresql:42.2.10'
dependency 'org.mockito:mockito-core:3.0.0'
dependency 'org.postgresql:postgresql:42.2.16'
}
}

View File

@@ -40,7 +40,7 @@ import org.springframework.session.events.SessionDestroyedEvent;
*
* {@literal @Bean}
* public MapSessionRepository sessionRepository() {
* return new MapSessionRepository(new ConcurrentHashMap<>());
* return new MapSessionRepository();
* }
*
* }

View File

@@ -58,7 +58,7 @@ import org.springframework.util.ObjectUtils;
*
* {@literal @Bean}
* public MapSessionRepository sessionRepository() {
* return new MapSessionRepository(new ConcurrentHashMap<>());
* return new MapSessionRepository();
* }
*
* }

View File

@@ -36,7 +36,7 @@ import org.springframework.context.annotation.Import;
*
* {@literal @Bean}
* public ReactiveSessionRepository sessionRepository() {
* return new ReactiveMapSessionRepository(new ConcurrentHashMap<>());
* return new ReactiveMapSessionRepository();
* }
*
* }

View File

@@ -309,6 +309,10 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
if (!create) {
return null;
}
if (SessionRepositoryFilter.this.httpSessionIdResolver instanceof CookieHttpSessionIdResolver
&& this.response.isCommitted()) {
throw new IllegalStateException("Cannot create a session after the response has been committed");
}
if (SESSION_LOGGER.isDebugEnabled()) {
SESSION_LOGGER.debug(
"A new session was created. To help you troubleshoot where the session was created we provided a StackTrace (this is not an error). You can prevent this from appearing by disabling DEBUG logging for "

View File

@@ -62,6 +62,7 @@ import org.springframework.test.util.ReflectionTestUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.assertj.core.api.Assertions.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
@@ -423,6 +424,18 @@ class SessionRepositoryFilterTests {
assertThat(this.response.getCookie("SESSION")).isNotNull();
}
@Test
void doFilterGetSessionNewWhenResponseCommittedThenException() {
assertThatIllegalStateException().isThrownBy(() -> doFilter(new DoInFilter() {
@Override
public void doFilter(HttpServletRequest wrappedRequest, HttpServletResponse wrappedResponse)
throws IOException {
wrappedResponse.getWriter().flush();
wrappedRequest.getSession();
}
}));
}
@Test
void doFilterGetSessionNew() throws Exception {
doFilter(new DoInFilter() {

View File

@@ -142,7 +142,7 @@ import org.springframework.util.Assert;
* <p>
* When a session is created an event is sent to Redis with the channel of
* "spring:session:channel:created:33fdd1b6-b496-4b33-9f7d-df96679d32fe" such that
* "33fdd1b6-b496-4b33-9f7d-df96679d32fe" is the session id. The body of the event will be
* "33fdd1b6-b496-4b33-9f7d-df96679d32fe" is the sesion id. The body of the event will be
* the session that was created.
* </p>
*

View File

@@ -46,7 +46,11 @@ asciidoctor {
'spring-session-version': project.version,
'version-milestone': milestoneBuild,
'version-release': releaseBuild,
'version-snapshot': snapshotBuild,
'highlightjsdir@': "js/highlight",
'docinfodir@': "."
'version-snapshot': snapshotBuild
}
remotes {
docs {
host = "docs-ip.spring.io"
}
}

View File

@@ -1,16 +1,11 @@
= Spring Session - find by username
Rob Winch
:toc: left
:stylesdir: ../
:highlightjsdir: ../js/highlight
:docinfodir: guides
:toc:
This guide describes how to use Spring Session to find sessions by username.
NOTE: You can find the completed guide in the <<findbyusername-sample, findbyusername application>>.
[#index-link]
link:../index.html[Index]
[[findbyusername-assumptions]]
== Assumptions

View File

@@ -1,17 +1,11 @@
= Spring Session - Spring Boot
Rob Winch, Vedran Pavić
:toc: left
:stylesdir: ../
:highlightjsdir: ../js/highlight
:docinfodir: guides
:toc:
This guide describes how to use Spring Session to transparently leverage a relational database to back a web application's `HttpSession` when you use Spring Boot.
NOTE: You can find the completed guide in the <<httpsession-jdbc-boot-sample, httpsession-jdbc-boot sample application>>.
[#index-link]
link:../index.html[Index]
== Updating Dependencies
Before you use Spring Session, you must update your dependencies.

View File

@@ -1,17 +1,11 @@
= Spring Session - Spring Boot
Rob Winch, Vedran Pavić
:toc: left
:stylesdir: ../
:highlightjsdir: ../js/highlight
:docinfodir: guides
:toc:
This guide describes how to use Spring Session to transparently leverage Redis to back a web application's `HttpSession` when you use Spring Boot.
NOTE: You can find the completed guide in the <<boot-sample, boot sample application>>.
[#index-link]
link:../index.html[Index]
== Updating Dependencies
Before you use Spring Session, you must ensure your dependencies.
@@ -157,6 +151,6 @@ To do so, enter the following into your terminal, being sure to replace `7e8383a
----
$ redis-cli del spring:session:sessions:7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
----
====
=====
Now you can visit the application at http://localhost:8080/ and observe that we are no longer authenticated.

View File

@@ -1,10 +1,7 @@
= Spring Session - WebSocket
Rob Winch
:toc: left
:toc:
:websocketdoc-test-dir: {docs-test-dir}docs/websocket/
:stylesdir: ../
:highlightjsdir: ../js/highlight
:docinfodir: guides
This guide describes how to use Spring Session to ensure that WebSocket messages keep your HttpSession alive.
@@ -15,9 +12,6 @@ Specifically,it does not work with using https://www.jcp.org/en/jsr/detail?id=35
// end::disclaimer[]
[#index-link]
link:../index.html[Index]
== HttpSession Setup
The first step is to integrate Spring Session with the HttpSession. These steps are already outlined in the link:httpsession.html[HttpSession Guide].

View File

@@ -1,2 +0,0 @@
<script type="text/javascript" src="../js/tocbot/tocbot.min.js"></script>
<script type="text/javascript" src="../js/toc.js"></script>

View File

@@ -1,18 +1,12 @@
= Spring Session - Custom Cookie
Rob Winch; Eleftheria Stein-Kousathana
:toc: left
:stylesdir: ../
:highlightjsdir: ../js/highlight
:docinfodir: guides
:toc:
This guide describes how to configure Spring Session to use custom cookies with Java Configuration.
The guide assumes you have already link:./httpsession.html[set up Spring Session in your project].
NOTE: You can find the completed guide in the <<custom-cookie-sample, Custom Cookie sample application>>.
[#index-link]
link:../index.html[Index]
[[custom-cookie-spring-configuration]]
== Spring Java Configuration

View File

@@ -1,18 +1,12 @@
= Spring Session and Spring Security with Hazelcast
Tommy Ludwig; Rob Winch
:toc: left
:stylesdir: ../
:highlightjsdir: ../js/highlight
:docinfodir: guides
:toc:
This guide describes how to use Spring Session along with Spring Security when you use Hazelcast as your data store.
It assumes that you have already applied Spring Security to your application.
NOTE: You cand find the completed guide in the <<hazelcast-spring-security-sample, Hazelcast Spring Security sample application>>.
[#index-link]
link:../index.html[Index]
== Updating Dependencies
Before you use Spring Session, you must update your dependencies.

View File

@@ -1,17 +1,11 @@
= Spring Session - HttpSession (Quick Start)
Rob Winch, Vedran Pavić
:toc: left
:stylesdir: ../
:highlightjsdir: ../js/highlight
:docinfodir: guides
:toc:
This guide describes how to use Spring Session to transparently leverage a relational database to back a web application's `HttpSession` with Java Configuration.
NOTE: You can find the completed guide in the <<httpsession-jdbc-sample, httpsession-jdbc sample application>>.
[#index-link]
link:../index.html[Index]
== Updating Dependencies
Before you use Spring Session, you must update your dependencies.
@@ -105,7 +99,7 @@ For additional information on how to configure data access related concerns, see
== Java Servlet Container Initialization
Our <<httpsession-jdbc-spring-configuration,Spring Configuration>> created a Spring bean named `springSessionRepositoryFilter` that implements `Filter`.
Our <<httpsession-spring-configuration,Spring Configuration>> created a Spring bean named `springSessionRepositoryFilter` that implements `Filter`.
The `springSessionRepositoryFilter` bean is responsible for replacing the `HttpSession` with a custom implementation that is backed by Spring Session.
In order for our `Filter` to do its magic, Spring needs to load our `Config` class.

View File

@@ -1,18 +1,12 @@
= Spring Session - HttpSession (Quick Start)
Rob Winch
:toc: left
:toc:
:version-snapshot: true
:stylesdir: ../
:highlightjsdir: ../js/highlight
:docinfodir: guides
This guide describes how to use Spring Session to transparently leverage Redis to back a web application's `HttpSession` with Java Configuration.
NOTE: You can find the completed guide in the <<httpsession-sample, httpsession sample application>>.
[#index-link]
link:../index.html[Index]
== Updating Dependencies
Before you use Spring Session, you must update your dependencies.
If you are using Maven, you must add the following dependencies:

View File

@@ -1,17 +1,11 @@
= Spring Session - REST
Rob Winch
:toc: left
:stylesdir: ../
:highlightjsdir: ../js/highlight
:docinfodir: guides
:toc:
This guide describes how to use Spring Session to transparently leverage Redis to back a web application's `HttpSession` when you use REST endpoints.
NOTE: You can find the completed guide in the <<rest-sample, rest sample application>>.
[#index-link]
link:../index.html[Index]
== Updating Dependencies
Before you use Spring Session, you must update your dependencies.
@@ -247,7 +241,7 @@ $ curl -v http://localhost:8080/ -u user:password
In the output, you should notice the following:
====
===
----
HTTP/1.1 200 OK
...

View File

@@ -1,18 +1,12 @@
= Spring Session and Spring Security
Rob Winch
:toc: left
:stylesdir: ../
:highlightjsdir: ../js/highlight
:docinfodir: guides
:toc:
This guide describes how to use Spring Session along with Spring Security.
It assumes you have already applied Spring Security to your application.
NOTE: You can find the completed guide in the <<security-sample, security sample application>>.
[#index-link]
link:../index.html[Index]
== Updating Dependencies
Before you use Spring Session, you must update your dependencies.
If you use Maven, you must add the following dependencies:

View File

@@ -1,17 +1,11 @@
= Spring Session - HttpSession (Quick Start)
Rob Winch, Vedran Pavić
:toc: left
:stylesdir: ../
:highlightjsdir: ../js/highlight
:docinfodir: guides
:toc:
This guide describes how to use Spring Session to transparently leverage a relational to back a web application's `HttpSession` with XML based configuration.
NOTE: You can find the completed guide in the <<httpsession-jdbc-xml-sample, httpsession-jdbc-xml sample application>>.
[#index-link]
link:../index.html[Index]
== Updating Dependencies
Before you use Spring Session, you must update your dependencies.
@@ -74,8 +68,8 @@ You must have the following in your pom.xml:
<url>https://repo.spring.io/libs-milestone</url>
</repository>
----
====
endif::[]
====
// tag::config[]

View File

@@ -1,17 +1,11 @@
= Spring Session - HttpSession (Quick Start)
Rob Winch
:toc: left
:stylesdir: ../
:highlightjsdir: ../js/highlight
:docinfodir: guides
:toc:
This guide describes how to use Spring Session to transparently leverage Redis to back a web application's `HttpSession` with XML-based configuration.
NOTE: You can find the completed guide in the <<httpsession-xml-sample, httpsession-xml sample application>>.
[#index-link]
link:../index.html[Index]
== Updating Dependencies
Before you use Spring Session, you must update your dependencies.
If you use Maven, you must add the following dependencies:

View File

@@ -19,7 +19,6 @@ package docs.security;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@@ -42,16 +41,14 @@ public class RememberMeSecurityConfiguration extends WebSecurityConfigurerAdapte
protected void configure(HttpSecurity http) throws Exception {
http
// ... additional configuration ...
.rememberMe((rememberMe) -> rememberMe
.rememberMeServices(rememberMeServices())
);
.rememberMe()
.rememberMeServices(rememberMeServices());
// end::http-rememberme[]
http
.formLogin(Customizer.withDefaults())
.authorizeRequests((authorize) -> authorize
.anyRequest().authenticated()
);
.formLogin().and()
.authorizeRequests()
.anyRequest().authenticated();
}
// tag::rememberme-bean[]

View File

@@ -40,10 +40,9 @@ public class SecurityConfiguration<S extends Session> extends WebSecurityConfigu
// @formatter:off
http
// other config goes here...
.sessionManagement((sessionManagement) -> sessionManagement
.sessionManagement()
.maximumSessions(2)
.sessionRegistry(sessionRegistry())
);
.sessionRegistry(sessionRegistry());
// @formatter:on
}

View File

@@ -46,7 +46,7 @@ import org.springframework.test.context.web.WebAppConfiguration;
@WebAppConfiguration
class ClientServerHazelcastIndexedSessionRepositoryITests extends AbstractHazelcastIndexedSessionRepositoryITests {
private static GenericContainer container = new GenericContainer<>("hazelcast/hazelcast:3.12.3")
private static GenericContainer container = new GenericContainer<>("hazelcast/hazelcast:3.12.12")
.withExposedPorts(5701).withCopyFileToContainer(MountableFile.forClasspathResource("/hazelcast-server.xml"),
"/opt/hazelcast/hazelcast.xml");

View File

@@ -104,7 +104,7 @@ final class DatabaseContainers {
private static class MariaDb10Container extends MariaDBContainer<MariaDb10Container> {
MariaDb10Container() {
super("mariadb:10.4.8");
super("mariadb:10.4.18");
}
@Override

View File

@@ -103,7 +103,7 @@ import org.springframework.util.StringUtils;
* );
*
* CREATE UNIQUE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID);
* CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (EXPIRY_TIME);
* CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (EXPIRY_TIME);
* CREATE INDEX SPRING_SESSION_IX3 ON SPRING_SESSION (PRINCIPAL_NAME);
*
* CREATE TABLE SPRING_SESSION_ATTRIBUTES (

View File

@@ -1,6 +1,6 @@
dependencyManagement {
imports {
mavenBom 'com.fasterxml.jackson:jackson-bom:2.10.0'
mavenBom 'com.fasterxml.jackson:jackson-bom:2.10.5.20201202'
}
dependencies {
@@ -9,15 +9,15 @@ dependencyManagement {
dependency 'javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:1.2.2'
dependency 'javax.servlet.jsp:javax.servlet.jsp-api:2.3.3'
dependency 'org.apache.taglibs:taglibs-standard-jstlel:1.2.5'
dependency 'org.seleniumhq.selenium:htmlunit-driver:2.33.0'
dependency 'org.slf4j:jcl-over-slf4j:1.7.28'
dependency 'org.slf4j:log4j-over-slf4j:1.7.28'
dependency 'org.seleniumhq.selenium:htmlunit-driver:2.33.3'
dependency 'org.slf4j:jcl-over-slf4j:1.7.30'
dependency 'org.slf4j:log4j-over-slf4j:1.7.30'
dependency 'org.webjars:bootstrap:2.3.2'
dependency 'org.webjars:html5shiv:3.7.3'
dependency 'org.webjars:jquery:1.12.4'
dependency 'org.webjars:knockout:2.3.0'
dependency 'org.webjars:sockjs-client:0.3.4'
dependency 'org.webjars:stomp-websocket:2.3.0'
dependency 'org.webjars:stomp-websocket:2.3.4'
dependency 'org.webjars:webjars-taglib:0.3'
}
}

View File

@@ -53,6 +53,8 @@ class FindByUsernameTests {
private WebDriver driver;
private WebDriver driver2;
@BeforeEach
void setup() {
this.driver = MockMvcHtmlUnitDriverBuilder.mockMvcSetup(this.mockMvc).build();
@@ -61,6 +63,9 @@ class FindByUsernameTests {
@AfterEach
void tearDown() {
this.driver.quit();
if (this.driver2 != null) {
this.driver2.quit();
}
}
@Test
@@ -79,6 +84,25 @@ class FindByUsernameTests {
home.terminateButtonDisabled();
}
@Test
void terminateOtherSession() throws Exception {
HomePage forgotToLogout = home(this.driver);
this.driver2 = MockMvcHtmlUnitDriverBuilder.mockMvcSetup(this.mockMvc).build();
HomePage terminateFogotSession = home(this.driver2);
terminateFogotSession.terminateSession(forgotToLogout.getSessionId()).assertAt();
LoginPage login = HomePage.go(this.driver);
login.assertAt();
}
private static HomePage home(WebDriver driver) {
LoginPage login = HomePage.go(driver);
HomePage home = login.form().login(HomePage.class);
home.assertAt();
return home;
}
@TestConfiguration
static class Config {

View File

@@ -56,6 +56,18 @@ public class HomePage extends BasePage {
}
public void terminateButtonDisabled() {
String sessionId = getSessionId();
WebElement element = getDriver().findElement(By.id("terminate-" + sessionId));
assertThat(element.isEnabled()).isFalse();
}
public HomePage terminateSession(String sessionId) {
WebElement terminate = getDriver().findElement(By.id("terminate-" + sessionId));
terminate.click();
return new HomePage(getDriver());
}
public String getSessionId() {
Set<Cookie> cookies = getDriver().manage().getCookies();
String cookieValue = null;
for (Cookie cookie : cookies) {
@@ -63,8 +75,7 @@ public class HomePage extends BasePage {
cookieValue = new String(Base64.getDecoder().decode(cookie.getValue()));
}
}
WebElement element = getDriver().findElement(By.id("terminate-" + cookieValue));
assertThat(element.isEnabled()).isFalse();
return cookieValue;
}
public HomePage logout() {

View File

@@ -35,14 +35,13 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests((authorize) -> authorize
.authorizeRequests()
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
.anyRequest().authenticated()
)
.formLogin((formLogin) -> formLogin
.and()
.formLogin()
.loginPage("/login")
.permitAll()
);
.permitAll();
}
// end::config[]
// @formatter:on

View File

@@ -26,8 +26,8 @@ import org.springframework.session.Session;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
/**
* Controller for sending the user to the login view.
@@ -50,7 +50,7 @@ public class IndexController {
}
// end::findbyusername[]
@RequestMapping(value = "/sessions/{sessionIdToDelete}", method = RequestMethod.DELETE)
@PostMapping("/sessions/{sessionIdToDelete}")
public String removeSession(Principal principal, @PathVariable String sessionIdToDelete) {
Set<String> usersSessionIds = this.sessions.findByPrincipalName(principal.getName()).keySet();
if (usersSessionIds.contains(sessionIdToDelete)) {

View File

@@ -25,7 +25,7 @@
<td th:text="${#temporals.format(sessionElement.lastAccessedTime.atZone(T(java.time.ZoneId).systemDefault()),'dd/MMM/yyyy HH:mm:ss')}"></td>
<td th:text="${details?.accessType}"></td>
<td>
<form th:action="@{'/sessions/' + ${sessionElement.id}}" th:method="delete">
<form th:action="@{'/sessions/' + ${sessionElement.id}}" th:method="post">
<input th:id="'terminate-' + ${sessionElement.id}" type="submit" value="Terminate" th:disabled="${sessionElement.id == #httpSession.id}"/>
</form>
</td>

View File

@@ -44,13 +44,12 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests((authorize) -> authorize
.authorizeRequests()
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
.anyRequest().authenticated()
)
.formLogin((formLogin) -> formLogin
.permitAll()
);
.and()
.formLogin()
.permitAll();
}
// end::config[]
// @formatter:on

View File

@@ -34,14 +34,13 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests((authorize) -> authorize
.authorizeRequests()
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
.anyRequest().authenticated()
)
.formLogin((formLogin) -> formLogin
.and()
.formLogin()
.loginPage("/login")
.permitAll()
);
.permitAll();
}
// @formatter:on

View File

@@ -28,13 +28,12 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests((authorize) -> authorize
.authorizeRequests()
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
.anyRequest().authenticated()
)
.formLogin((formLogin) -> formLogin
.permitAll()
);
.and()
.formLogin()
.permitAll();
}
// @formatter:on

View File

@@ -35,13 +35,12 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests((authorize) -> authorize
.authorizeRequests()
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
.anyRequest().authenticated()
)
.formLogin((formLogin) -> formLogin
.permitAll()
);
.and()
.formLogin()
.permitAll();
}
// end::config[]
// @formatter:on

View File

@@ -53,13 +53,12 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests((authorize) -> authorize
.authorizeRequests()
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
.anyRequest().authenticated()
)
.formLogin((formLogin) -> formLogin
.permitAll()
);
.and()
.formLogin()
.permitAll();
}
// @formatter:on

View File

@@ -37,4 +37,4 @@ public class SessionServlet extends HttpServlet {
private static final long serialVersionUID = 2878267318695777395L;
}
// end::class[]
// tag::end[]

View File

@@ -38,4 +38,4 @@ public class SessionServlet extends HttpServlet {
private static final long serialVersionUID = 2878267318695777395L;
}
// end::class[]
// tag::end[]

View File

@@ -17,7 +17,6 @@
package sample;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
@@ -32,13 +31,13 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests((authorize) -> authorize
.authorizeRequests()
.anyRequest().authenticated()
)
.requestCache((requestCache) -> requestCache
.and()
.requestCache()
.requestCache(new NullRequestCache())
)
.httpBasic(Customizer.withDefaults());
.and()
.httpBasic();
}
// @formatter:on