Compare commits
226 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5d521aa9bc | ||
|
|
e14c840354 | ||
|
|
f36713d0ee | ||
|
|
12721d83ad | ||
|
|
92c7302103 | ||
|
|
1adb9bb481 | ||
|
|
8faef3613b | ||
|
|
65702d159e | ||
|
|
48f061450c | ||
|
|
a77196a851 | ||
|
|
4d18ed1826 | ||
|
|
b20dd33af7 | ||
|
|
ad51021e22 | ||
|
|
41a84efd21 | ||
|
|
6cb1764066 | ||
|
|
07f16ffc6a | ||
|
|
54b428dbeb | ||
|
|
e789fcc628 | ||
|
|
15d22a9dd4 | ||
|
|
40cb8de232 | ||
|
|
b394f56731 | ||
|
|
e7fd59ccf9 | ||
|
|
6e5352d48f | ||
|
|
2507c86cba | ||
|
|
01f7ff9a51 | ||
|
|
1ce95f8591 | ||
|
|
a9d003af4d | ||
|
|
797b0a62a8 | ||
|
|
943abb8eca | ||
|
|
9f78688ffa | ||
|
|
c391adfea1 | ||
|
|
9befe44769 | ||
|
|
6aa85236e0 | ||
|
|
5ebe699d7c | ||
|
|
f6a670d78e | ||
|
|
c63761317d | ||
|
|
f0aed6b8b8 | ||
|
|
4a3f0d5f34 | ||
|
|
5d88b6bf28 | ||
|
|
b7857db5bb | ||
|
|
8e97ac9acd | ||
|
|
ca943b6717 | ||
|
|
08c3056fb5 | ||
|
|
ca41542113 | ||
|
|
2e4f12e1a7 | ||
|
|
d582343a7e | ||
|
|
2505270f5f | ||
|
|
02e182ab4a | ||
|
|
8f13a7b356 | ||
|
|
51252a55e6 | ||
|
|
4487b07bb1 | ||
|
|
84479a0ba0 | ||
|
|
643f9cfd1a | ||
|
|
95e6d710ba | ||
|
|
0cf723c6aa | ||
|
|
66cc442b5f | ||
|
|
23d8c18b22 | ||
|
|
28d1d4fd00 | ||
|
|
e82a856d00 | ||
|
|
e40e55d1e9 | ||
|
|
a289938c7c | ||
|
|
63927aa4da | ||
|
|
88071796a2 | ||
|
|
76bc9563bb | ||
|
|
819b341a9f | ||
|
|
3b0be07c8e | ||
|
|
6761f2cc68 | ||
|
|
c8f266cea2 | ||
|
|
7d71aa5d00 | ||
|
|
bee9c7c2e2 | ||
|
|
8788165966 | ||
|
|
aadc806447 | ||
|
|
0fb942f795 | ||
|
|
49ebaa5cb7 | ||
|
|
a48edd5e71 | ||
|
|
17ddfc0fa8 | ||
|
|
f2f9562a01 | ||
|
|
4c50da3982 | ||
|
|
b1d53874e4 | ||
|
|
cc2a75b668 | ||
|
|
006acba02a | ||
|
|
168ad85cc5 | ||
|
|
3f61a30568 | ||
|
|
318036828d | ||
|
|
326e7070b1 | ||
|
|
81ca7d5f83 | ||
|
|
de8e47e4c3 | ||
|
|
ef6b9f8812 | ||
|
|
14be439da0 | ||
|
|
2631ddc446 | ||
|
|
1e15f0d010 | ||
|
|
87c4fb7103 | ||
|
|
e05ca40d26 | ||
|
|
68615cdfce | ||
|
|
51f9bd17ac | ||
|
|
15f7d91660 | ||
|
|
edbeb98f9a | ||
|
|
354346a62c | ||
|
|
aa81c18093 | ||
|
|
d426792b57 | ||
|
|
2007f45ea0 | ||
|
|
3d8fa846d5 | ||
|
|
c9c172ce89 | ||
|
|
8b189962eb | ||
|
|
ea84b8bd22 | ||
|
|
0c9fbedd05 | ||
|
|
08495b1321 | ||
|
|
60cd6d8be6 | ||
|
|
5503057523 | ||
|
|
8fc2f1130a | ||
|
|
f5d63efcf1 | ||
|
|
ed76514f30 | ||
|
|
e1c0d62d33 | ||
|
|
8041358d18 | ||
|
|
cdd85cb349 | ||
|
|
381a07cb8c | ||
|
|
0e89539e20 | ||
|
|
f00a1b9c6f | ||
|
|
39cecb0902 | ||
|
|
c5fc4b57ad | ||
|
|
3b826e51a1 | ||
|
|
67063ec0c6 | ||
|
|
72198e9e80 | ||
|
|
b3ee28b972 | ||
|
|
2d498bf69d | ||
|
|
c365e4d941 | ||
|
|
f7f8d4f6c0 | ||
|
|
fd5115fae5 | ||
|
|
a4c39fde9f | ||
|
|
96391ce41a | ||
|
|
d48eebea99 | ||
|
|
57cd6c367d | ||
|
|
68f83b00eb | ||
|
|
a4a5b529ef | ||
|
|
f5ae38d94c | ||
|
|
b201ed971c | ||
|
|
70346b0a84 | ||
|
|
d4fd8b97b4 | ||
|
|
b3d01063d9 | ||
|
|
124565306b | ||
|
|
f709a6c787 | ||
|
|
c354927ef3 | ||
|
|
2db79e2bb8 | ||
|
|
3480c65c2b | ||
|
|
e0dc0262ef | ||
|
|
3b7da0c370 | ||
|
|
72984f9ca6 | ||
|
|
8a4872b919 | ||
|
|
6b6c6f27df | ||
|
|
640bee3fc4 | ||
|
|
3bfdb9be93 | ||
|
|
c8f3d1a1ec | ||
|
|
11ad1db6e7 | ||
|
|
7b87128db6 | ||
|
|
bf861933ed | ||
|
|
979e91256d | ||
|
|
05986d68b2 | ||
|
|
e17b047800 | ||
|
|
5ab2424b14 | ||
|
|
196919efbb | ||
|
|
717e16cb71 | ||
|
|
5f1b7d6722 | ||
|
|
4d3a01919c | ||
|
|
e408d7f557 | ||
|
|
f34acebf84 | ||
|
|
1aab3e8285 | ||
|
|
c3528996d2 | ||
|
|
3ccc3eb6e1 | ||
|
|
de76be95ac | ||
|
|
bc127ab3fc | ||
|
|
3e9f6a35c4 | ||
|
|
49daa3a9c7 | ||
|
|
a67bd634d9 | ||
|
|
2762f001bf | ||
|
|
93aee206fb | ||
|
|
3df3b30117 | ||
|
|
5fb0c4dd35 | ||
|
|
6fbce6e3e8 | ||
|
|
a3fd05326a | ||
|
|
4c6dc976b3 | ||
|
|
58ae28b0a0 | ||
|
|
3e98ecf234 | ||
|
|
41ed429f98 | ||
|
|
def15b05ca | ||
|
|
eae8592f2b | ||
|
|
81460ede09 | ||
|
|
ca4ec9a557 | ||
|
|
fd2165f471 | ||
|
|
ad1e57a1fe | ||
|
|
0ffcaa2d35 | ||
|
|
b61937def7 | ||
|
|
c523fb591d | ||
|
|
227fab2e42 | ||
|
|
7f7815d80c | ||
|
|
002136bad4 | ||
|
|
1085661984 | ||
|
|
12bb0741bb | ||
|
|
eecdcb49d9 | ||
|
|
3e1a22102d | ||
|
|
9f6e791e5d | ||
|
|
efc35eddad | ||
|
|
4c37ec9f4a | ||
|
|
1a3da5944d | ||
|
|
5d0775b802 | ||
|
|
603a258172 | ||
|
|
22ebe65931 | ||
|
|
55033bcb64 | ||
|
|
57955b7d7b | ||
|
|
d5da38f2e0 | ||
|
|
6cc4bcd13d | ||
|
|
dc43f5bd2d | ||
|
|
7584cbd54c | ||
|
|
0db1160dc4 | ||
|
|
10a18366f9 | ||
|
|
7ea5e2f3ee | ||
|
|
d3134ad065 | ||
|
|
6208d0298d | ||
|
|
c031ee278d | ||
|
|
8267a90fcc | ||
|
|
2113b330a7 | ||
|
|
c4ac68b777 | ||
|
|
0be2759e68 | ||
|
|
1181e52bb0 | ||
|
|
5277d945ed | ||
|
|
1fc0162fe9 | ||
|
|
9df259b1ae |
18
.travis.yml
18
.travis.yml
@@ -1,20 +1,16 @@
|
||||
language: java
|
||||
|
||||
sudo: required
|
||||
|
||||
services: docker
|
||||
|
||||
jdk: oraclejdk8
|
||||
|
||||
language: java
|
||||
jdk:
|
||||
- openjdk8
|
||||
- openjdk11
|
||||
services:
|
||||
- docker
|
||||
before_cache:
|
||||
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
|
||||
- rm -fr $HOME/.gradle/caches/*/plugin-resolution/
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.gradle/caches/
|
||||
- $HOME/.gradle/wrapper/
|
||||
|
||||
install: true
|
||||
|
||||
script: ./gradlew clean build --refresh-dependencies --no-daemon
|
||||
script: ./gradlew clean check --no-daemon --refresh-dependencies --stacktrace
|
||||
|
||||
@@ -40,5 +40,5 @@ appropriate to the circumstances. Maintainers are obligated to maintain confiden
|
||||
with regard to the reporter of an incident.
|
||||
|
||||
This Code of Conduct is adapted from the
|
||||
http://contributor-covenant.org[Contributor Covenant], version 1.3.0, available at
|
||||
http://contributor-covenant.org/version/1/3/0/[contributor-covenant.org/version/1/3/0/]
|
||||
https://contributor-covenant.org[Contributor Covenant], version 1.3.0, available at
|
||||
https://contributor-covenant.org/version/1/3/0/[contributor-covenant.org/version/1/3/0/]
|
||||
|
||||
@@ -10,8 +10,8 @@ By participating, you are expected to uphold this code. Please report unaccepta
|
||||
== Using GitHub issues
|
||||
|
||||
We use GitHub issues to track bugs and enhancements. If you have a general usage question
|
||||
please ask on http://stackoverflow.com[Stack Overflow]. The Spring Session team and the
|
||||
broader community monitor the http://stackoverflow.com/tags/spring-session[`spring-session`]
|
||||
please ask on https://stackoverflow.com[Stack Overflow]. The Spring Session team and the
|
||||
broader community monitor the https://stackoverflow.com/tags/spring-session[`spring-session`]
|
||||
tag.
|
||||
|
||||
If you are reporting a bug, please help to speed up problem diagnosis by providing as much
|
||||
|
||||
95
Jenkinsfile
vendored
95
Jenkinsfile
vendored
@@ -1,95 +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: 30, unit: 'MINUTES') {
|
||||
node {
|
||||
checkout scm
|
||||
try {
|
||||
sh './gradlew clean check --no-daemon --refresh-dependencies'
|
||||
}
|
||||
catch (e) {
|
||||
currentBuild.result = 'FAILED: check'
|
||||
throw e
|
||||
}
|
||||
finally {
|
||||
junit '**/build/*-results/*.xml'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (currentBuild.result == 'SUCCESS') {
|
||||
parallel artifacts: {
|
||||
stage('Deploy Artifacts') {
|
||||
node {
|
||||
checkout scm
|
||||
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')]) {
|
||||
sh './gradlew deployArtifacts finalizeDeployArtifacts --stacktrace --no-daemon --refresh-dependencies -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 {
|
||||
checkout scm
|
||||
try {
|
||||
withCredentials([file(credentialsId: 'docs.spring.io-jenkins_private_ssh_key', variable: 'DEPLOY_SSH_KEY')]) {
|
||||
sh './gradlew deployDocs --stacktrace --no-daemon --refresh-dependencies -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"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
https://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
@@ -193,7 +193,7 @@
|
||||
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
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
10
README.adoc
10
README.adoc
@@ -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"]
|
||||
@@ -25,8 +31,8 @@ By participating, you are expected to uphold this code. Please report unaccepta
|
||||
|
||||
== 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 https://projects.spring.io/spring-session/
|
||||
|
||||
== License
|
||||
|
||||
Spring Session is Open Source software released under the http://www.apache.org/licenses/LICENSE-2.0.html[Apache 2.0 license].
|
||||
Spring Session is Open Source software released under the https://www.apache.org/licenses/LICENSE-2.0.html[Apache 2.0 license].
|
||||
|
||||
30
build.gradle
30
build.gradle
@@ -1,20 +1,30 @@
|
||||
buildscript {
|
||||
ext {
|
||||
releaseBuild = version.endsWith('RELEASE')
|
||||
snapshotBuild = version.endsWith('SNAPSHOT')
|
||||
milestoneBuild = !(releaseBuild || snapshotBuild)
|
||||
|
||||
springBootVersion = '2.1.16.RELEASE'
|
||||
}
|
||||
|
||||
repositories {
|
||||
gradlePluginPortal()
|
||||
maven { url 'https://repo.spring.io/plugins-release/' }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'io.spring.gradle:spring-build-conventions:0.0.17.RELEASE'
|
||||
classpath 'io.spring.gradle:spring-build-conventions:0.0.25.RELEASE'
|
||||
classpath "org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion"
|
||||
}
|
||||
repositories {
|
||||
maven { url 'https://repo.spring.io/plugins-release' }
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'io.spring.convention.root'
|
||||
|
||||
group = 'org.springframework.session'
|
||||
description = 'Spring Session'
|
||||
|
||||
|
||||
ext.releaseBuild = version.endsWith('RELEASE')
|
||||
ext.snapshotBuild = version.endsWith('SNAPSHOT')
|
||||
ext.milestoneBuild = !(releaseBuild || snapshotBuild)
|
||||
|
||||
|
||||
subprojects {
|
||||
plugins.withType(JavaPlugin) {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,137 +4,141 @@ Rob Winch
|
||||
|
||||
This guide describes how to use Spring Session to find sessions by username.
|
||||
|
||||
NOTE: The completed guide can be found in the <<findbyusername-sample, findbyusername application>>.
|
||||
NOTE: You can find the completed guide in the <<findbyusername-sample, findbyusername application>>.
|
||||
|
||||
|
||||
[[findbyusername-assumptions]]
|
||||
== Assumptions
|
||||
|
||||
The guide assumes you have already added Spring Session using the built in Redis configuration support to your application.
|
||||
The guide assumes you have already added Spring Session to your application by using the built-in Redis configuration support.
|
||||
The guide also assumes you have already applied Spring Security to your application.
|
||||
However, we the guide will be somewhat general purpose and can be applied to any technology with minimal changes we will discuss.
|
||||
However, we the guide is somewhat general purpose and can be applied to any technology with minimal changes, which we discuss later in the guide.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
If you need to learn how to add Spring Session to your project, please refer to the listing of link:../#samples[samples and guides]
|
||||
====
|
||||
NOTE: If you need to learn how to add Spring Session to your project, see the listing of link:../#samples[samples and guides]
|
||||
|
||||
== About the Sample
|
||||
|
||||
Our sample is using this feature to invalidate the users session that might have been compromised.
|
||||
Our sample uses this feature to invalidate the users session that might have been compromised.
|
||||
Consider the following scenario:
|
||||
|
||||
* User goes to library and authenticates to the application
|
||||
* User goes home and realizes they forgot to log out
|
||||
* User can log in and terminate the session from the library using clues like the location, created time, last accessed time, etc.
|
||||
* User goes to library and authenticates to the application.
|
||||
* User goes home and realizes they forgot to log out.
|
||||
* User can log in and terminate the session from the library using clues like the location, created time, last accessed time, and so on.
|
||||
|
||||
Wouldn't it be nice if we could allow the user to invalidate the session at the library from any device they authenticate with?
|
||||
Would it not be nice if we could let the user invalidate the session at the library from any device with which they authenticate?
|
||||
This sample demonstrates how this is possible.
|
||||
|
||||
[[findbyindexnamesessionrepository]]
|
||||
== FindByIndexNameSessionRepository
|
||||
== Using `FindByIndexNameSessionRepository`
|
||||
|
||||
In order to look up a user by their username, you must first choose a `SessionRepository` that implements link:../#api-findbyindexnamesessionrepository[FindByIndexNameSessionRepository].
|
||||
Our sample application assumes that the Redis support is already setup, so we are ready to go.
|
||||
To look up a user by their username, you must first choose a `SessionRepository` that implements link:../#api-findbyindexnamesessionrepository[`FindByIndexNameSessionRepository`].
|
||||
Our sample application assumes that the Redis support is already set up, so we are ready to go.
|
||||
|
||||
== Mapping the username
|
||||
== Mapping the User Name
|
||||
|
||||
`FindByIndexNameSessionRepository` can only find a session by the username, if the developer instructs Spring Session what user is associated with the `Session`.
|
||||
This is done by ensuring that the session attribute with the name `FindByUsernameSessionRepository.PRINCIPAL_NAME_INDEX_NAME` is populated with the username.
|
||||
`FindByIndexNameSessionRepository` can find a session only by the user name if the developer instructs Spring Session what user is associated with the `Session`.
|
||||
You can do so by ensuring that the session attribute with the name `FindByUsernameSessionRepository.PRINCIPAL_NAME_INDEX_NAME` is populated with the username.
|
||||
|
||||
Generally, speaking this can be done with the following code immediately after the user authenticates:
|
||||
Generally speaking, you can do so with the following code immediately after the user authenticates:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::{docs-test-dir}docs/FindByIndexNameSessionRepositoryTests.java[tags=set-username]
|
||||
----
|
||||
====
|
||||
|
||||
== Mapping the username with Spring Security
|
||||
== Mapping the User Name with Spring Security
|
||||
|
||||
Since we are using Spring Security, the user name is automatically indexed for us.
|
||||
This means we will not have to perform any steps to ensure the user name is indexed.
|
||||
Since we use Spring Security, the user name is automatically indexed for us.
|
||||
This means we need not perform any steps to ensure the user name is indexed.
|
||||
|
||||
== Adding Additional Data to Session
|
||||
== Adding Additional Data to the Session
|
||||
|
||||
It may be nice to associate additional information (i.e. IP Address, the browser, location, etc) to the session.
|
||||
This makes it easier for the user to know which session they are looking at.
|
||||
It may be nice to associate additional information (such as the IP Address, the browser, location, and other details) to the session.
|
||||
Doing so makes it easier for the user to know which session they are looking at.
|
||||
|
||||
To do this simply determine which session attribute you want to use and what information you wish to provide.
|
||||
To do so, determine which session attribute you want to use and what information you wish to provide.
|
||||
Then create a Java bean that is added as a session attribute.
|
||||
For example, our sample application includes the location and access type of the session
|
||||
For example, our sample application includes the location and access type of the session, as the following listing shows:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::{samples-dir}boot/findbyusername/src/main/java/sample/session/SessionDetails.java[tags=class]
|
||||
----
|
||||
====
|
||||
|
||||
We then inject that information into the session on each HTTP request using a `SessionDetailsFilter`.
|
||||
For example:
|
||||
We then inject that information into the session on each HTTP request using a `SessionDetailsFilter`, as the following example shows:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::{samples-dir}boot/findbyusername/src/main/java/sample/session/SessionDetailsFilter.java[tags=dofilterinternal]
|
||||
----
|
||||
====
|
||||
|
||||
We obtain the information we want and then set the `SessionDetails` as an attribute in the `Session`.
|
||||
When we retrieve the `Session` by username, we can then use the session to access our `SessionDetails` just like any other session attribute.
|
||||
When we retrieve the `Session` by user name, we can then use the session to access our `SessionDetails` as we would any other session attribute.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
You might be wondering at this point why Spring Session does not provide `SessionDetails` functionality out of the box.
|
||||
The reason, is twofold.
|
||||
The first is that it is very trivial for applications to implement this themselves.
|
||||
The second reason is that the information that is populated in the session (and how frequently that information is updated) is highly application dependent.
|
||||
====
|
||||
NOTE: You might wonder why Spring Session does not provide `SessionDetails` functionality out of the box.
|
||||
We have two reasons.
|
||||
The first reason is that it is very trivial for applications to implement this themselves.
|
||||
The second reason is that the information that is populated in the session (and how frequently that information is updated) is highly application-dependent.
|
||||
|
||||
== Finding sessions for a specific user
|
||||
|
||||
We can now find all the sessions for a specific user.
|
||||
The following example shows how to do so:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::{samples-dir}boot/findbyusername/src/main/java/sample/mvc/IndexController.java[tags=findbyusername]
|
||||
----
|
||||
====
|
||||
|
||||
In our instance, we find all sessions for the currently logged in user.
|
||||
However, this could easily be modified for an administrator to use a form to specify which user to look up.
|
||||
However, you can modify this for an administrator to use a form to specify which user to look up.
|
||||
|
||||
[[findbyusername-sample]]
|
||||
== findbyusername Sample Application
|
||||
== `findbyusername` Sample Application
|
||||
|
||||
=== Running the findbyusername Sample Application
|
||||
This section describes how to use the `findbyusername` sample application.
|
||||
|
||||
=== Running the `findbyusername` Sample Application
|
||||
|
||||
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 https://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
|
||||
Alternatively, you can update the `RedisConnectionFactory` to point to a Redis server.
|
||||
Another option is to use https://www.docker.com/[Docker] to run Redis on localhost. See https://hub.docker.com/_/redis/[Docker Redis repository] for detailed instructions.
|
||||
====
|
||||
|
||||
----
|
||||
$ ./gradlew :spring-session-sample-boot-findbyusername:bootRun
|
||||
----
|
||||
====
|
||||
|
||||
NOTE: For the sample to work, you must https://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
|
||||
Alternatively, you can update the `RedisConnectionFactory` to point to a Redis server.
|
||||
Another option is to use https://www.docker.com/[Docker] to run Redis on localhost.
|
||||
See https://hub.docker.com/_/redis/[Docker Redis repository] for detailed instructions.
|
||||
|
||||
You should now be able to access the application at http://localhost:8080/
|
||||
|
||||
=== Exploring the security Sample Application
|
||||
|
||||
Try using the application. Enter the following to log in:
|
||||
You can now try using the application. Enter the following to log in:
|
||||
|
||||
* **Username** _user_
|
||||
* **Password** _password_
|
||||
* *Username* _user_
|
||||
* *Password* _password_
|
||||
|
||||
Now click the **Login** button.
|
||||
Now click the *Login* button.
|
||||
You should now see a message indicating your are logged in with the user entered previously.
|
||||
You should also see a listing of active sessions for the currently logged in user.
|
||||
|
||||
Let's emulate the flow we discussed in the <<About the Sample>> section
|
||||
You can emulate the flow we discussed in the <<About the Sample>> section by doing the following:
|
||||
|
||||
* Open a new incognito window and navigate to http://localhost:8080/
|
||||
* Enter the following to log in:
|
||||
** **Username** _user_
|
||||
** **Password** _password_
|
||||
* Terminate your original session
|
||||
* Refresh the original window and see you are logged out
|
||||
** *Username* _user_
|
||||
** *Password* _password_
|
||||
* Terminate your original session.
|
||||
* Refresh the original window and see that you are logged out.
|
||||
|
||||
@@ -2,15 +2,17 @@
|
||||
Rob Winch, Vedran Pavić
|
||||
:toc:
|
||||
|
||||
This guide describes how to use Spring Session to transparently leverage a relational database to back a web application's `HttpSession` when using Spring Boot.
|
||||
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: The completed guide can be found in the <<httpsession-jdbc-boot-sample, httpsession-jdbc-boot sample application>>.
|
||||
NOTE: You can find the completed guide in the <<httpsession-jdbc-boot-sample, httpsession-jdbc-boot sample application>>.
|
||||
|
||||
== Updating Dependencies
|
||||
Before you use Spring Session, you must ensure to update your dependencies.
|
||||
We assume you are working with a working Spring Boot web application.
|
||||
If you are using Maven, ensure to add the following dependencies:
|
||||
|
||||
Before you use Spring Session, you must update your dependencies.
|
||||
We assume you are working with a working Spring Boot web application.
|
||||
If you use Maven, you must add the following dependencies:
|
||||
|
||||
====
|
||||
.pom.xml
|
||||
[source,xml]
|
||||
[subs="verbatim,attributes"]
|
||||
@@ -24,8 +26,9 @@ If you are using Maven, ensure to add the following dependencies:
|
||||
</dependency>
|
||||
</dependencies>
|
||||
----
|
||||
====
|
||||
|
||||
Spring Boot provides dependency management for Spring Session modules, so there's no need to explicitly declare dependency version.
|
||||
Spring Boot provides dependency management for Spring Session modules, so you need not explicitly declare the dependency version.
|
||||
|
||||
// tag::config[]
|
||||
|
||||
@@ -33,95 +36,106 @@ Spring Boot provides dependency management for Spring Session modules, so there'
|
||||
== Spring Boot Configuration
|
||||
|
||||
After adding the required dependencies, we can create our Spring Boot configuration.
|
||||
Thanks to first-class auto configuration support, setting up Spring Session backed by a relational database is as simple as adding a single configuration property to your `application.properties`:
|
||||
Thanks to first-class auto configuration support, setting up Spring Session backed by a relational database is as simple as adding a single configuration property to your `application.properties`.
|
||||
The following listing shows how to do so:
|
||||
|
||||
====
|
||||
.src/main/resources/application.properties
|
||||
----
|
||||
spring.session.store-type=jdbc # Session store type.
|
||||
----
|
||||
====
|
||||
|
||||
Under the hood, Spring Boot will apply configuration that is equivalent to manually adding `@EnableJdbcHttpSession` annotation.
|
||||
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.
|
||||
Under the hood, Spring Boot applies configuration that is equivalent to manually adding the `@EnableJdbcHttpSession` annotation.
|
||||
This creates a Spring bean with the name of `springSessionRepositoryFilter`. That bean implements `Filter`.
|
||||
The filter is in charge of replacing the `HttpSession` implementation to be backed by Spring Session.
|
||||
|
||||
Further customization is possible using `application.properties`:
|
||||
You can further customize by using `application.properties`.
|
||||
The following listing shows how to do so:
|
||||
|
||||
====
|
||||
.src/main/resources/application.properties
|
||||
----
|
||||
server.servlet.session.timeout= # Session timeout. If a duration suffix is not specified, seconds will be used.
|
||||
server.servlet.session.timeout= # Session timeout. If a duration suffix is not specified, seconds are used.
|
||||
spring.session.jdbc.initialize-schema=embedded # Database schema initialization mode.
|
||||
spring.session.jdbc.schema=classpath:org/springframework/session/jdbc/schema-@@platform@@.sql # Path to the SQL file to use to initialize the database schema.
|
||||
spring.session.jdbc.table-name=SPRING_SESSION # Name of the database table used to store sessions.
|
||||
----
|
||||
====
|
||||
|
||||
For more information, refer to https://docs.spring.io/spring-boot/docs/{spring-boot-version}/reference/htmlsingle/#boot-features-session[Spring Session] portion of the Spring Boot documentation.
|
||||
For more information, see the https://docs.spring.io/spring-boot/docs/{spring-boot-version}/reference/htmlsingle/#boot-features-session[Spring Session] portion of the Spring Boot documentation.
|
||||
|
||||
[[httpsession-jdbc-boot-configuration]]
|
||||
== Configuring the DataSource
|
||||
== Configuring the `DataSource`
|
||||
|
||||
Spring Boot automatically creates a `DataSource` that connects Spring Session to an embedded instance of H2 database.
|
||||
In a production environment you need to ensure to update your configuration to point to your relational database.
|
||||
For example, you can include the following in your *application.properties*
|
||||
Spring Boot automatically creates a `DataSource` that connects Spring Session to an embedded instance of an H2 database.
|
||||
In a production environment, you need to update your configuration to point to your relational database.
|
||||
For example, you can include the following in your application.properties:
|
||||
|
||||
====
|
||||
.src/main/resources/application.properties
|
||||
----
|
||||
spring.datasource.url= # JDBC URL of the database.
|
||||
spring.datasource.username= # Login username of the database.
|
||||
spring.datasource.password= # Login password of the database.
|
||||
----
|
||||
====
|
||||
|
||||
For more information, refer to https://docs.spring.io/spring-boot/docs/{spring-boot-version}/reference/htmlsingle/#boot-features-configure-datasource[Configure a DataSource] portion of the Spring Boot documentation.
|
||||
For more information, see the https://docs.spring.io/spring-boot/docs/{spring-boot-version}/reference/htmlsingle/#boot-features-configure-datasource[Configure a DataSource] portion of the Spring Boot documentation.
|
||||
|
||||
[[httpsession-jdbc-boot-servlet-configuration]]
|
||||
== Servlet Container Initialization
|
||||
|
||||
Our <<httpsession-jdbc-boot-spring-configuration,Spring Boot Configuration>> created a Spring Bean named `springSessionRepositoryFilter` that implements `Filter`.
|
||||
Our <<httpsession-jdbc-boot-spring-configuration,Spring Boot 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.
|
||||
Last we need to ensure that our Servlet Container (i.e. Tomcat) uses our `springSessionRepositoryFilter` for every request.
|
||||
Last, we need to ensure that our Servlet Container (that is, Tomcat) uses our `springSessionRepositoryFilter` for every request.
|
||||
Fortunately, Spring Boot takes care of both of these steps for us.
|
||||
|
||||
// end::config[]
|
||||
|
||||
[[httpsession-jdbc-boot-sample]]
|
||||
== httpsession-jdbc-boot Sample Application
|
||||
== `httpsession-jdbc-boot` Sample Application
|
||||
|
||||
The httpsession-jdbc-boot Sample Application demonstrates how to use Spring Session to transparently leverage H2 database to back a web application's `HttpSession` when using Spring Boot.
|
||||
The httpsession-jdbc-boot Sample Application demonstrates how to use Spring Session to transparently leverage an H2 database to back a web application's `HttpSession` when you use Spring Boot.
|
||||
|
||||
[[httpsession-jdbc-boot-running]]
|
||||
=== Running the httpsession-jdbc-boot Sample Application
|
||||
=== Running the `httpsession-jdbc-boot` Sample Application
|
||||
|
||||
You can run the sample by obtaining the {download-url}[source code] and invoking the following command:
|
||||
|
||||
====
|
||||
----
|
||||
$ ./gradlew :spring-session-sample-boot-jdbc:bootRun
|
||||
----
|
||||
====
|
||||
|
||||
You should now be able to access the application at http://localhost:8080/
|
||||
|
||||
[[httpsession-jdbc-boot-explore]]
|
||||
=== Exploring the security Sample Application
|
||||
=== Exploring the Security Sample Application
|
||||
|
||||
Try using the application. Enter the following to log in:
|
||||
You can now try using the application.
|
||||
To do so, enter the following to log in:
|
||||
|
||||
* **Username** _user_
|
||||
* **Password** _password_
|
||||
* *Username* _user_
|
||||
* *Password* _password_
|
||||
|
||||
Now click the **Login** button.
|
||||
You should now see a message indicating your are logged in with the user entered previously.
|
||||
The user's information is stored in H2 database rather than Tomcat's `HttpSession` implementation.
|
||||
Now click the *Login* button.
|
||||
You should now see a message indicating that your are logged in with the user entered previously.
|
||||
The user's information is stored in the H2 database rather than Tomcat's `HttpSession` implementation.
|
||||
|
||||
[[httpsession-jdbc-boot-how]]
|
||||
=== How does it work?
|
||||
=== How Does It Work?
|
||||
|
||||
Instead of using Tomcat's `HttpSession`, we are actually persisting the values in H2 database.
|
||||
Instead of using Tomcat's `HttpSession`, we persist the values in the H2 database.
|
||||
Spring Session replaces the `HttpSession` with an implementation that is backed by a relational database.
|
||||
When Spring Security's `SecurityContextPersistenceFilter` saves the `SecurityContext` to the `HttpSession` it is then persisted into H2 database.
|
||||
When Spring Security's `SecurityContextPersistenceFilter` saves the `SecurityContext` to the `HttpSession`, it is then persisted into the H2 database.
|
||||
|
||||
When a new `HttpSession` is created, Spring Session creates a cookie named SESSION in your browser that contains the id of your session.
|
||||
Go ahead and view the cookies (click for help with https://developers.google.com/web/tools/chrome-devtools/manage-data/cookies[Chrome] or https://developer.mozilla.org/en-US/docs/Tools/Storage_Inspector[Firefox]).
|
||||
When a new `HttpSession` is created, Spring Session creates a cookie named `SESSION` in your browser. That cookie contains the ID of your session.
|
||||
You can view the cookies (with https://developers.google.com/web/tools/chrome-devtools/manage-data/cookies[Chrome] or https://developer.mozilla.org/en-US/docs/Tools/Storage_Inspector[Firefox]).
|
||||
|
||||
If you like, you can easily remove the session using H2 web console available at: http://localhost:8080/h2-console/ (use `jdbc:h2:mem:testdb` for JDBC URL)
|
||||
You can remove the session by using the H2 web console available at: http://localhost:8080/h2-console/ (use `jdbc:h2:mem:testdb` for JDBC URL).
|
||||
|
||||
Now visit the application at http://localhost:8080/ and observe that we are no longer authenticated.
|
||||
Now you can visit the application at http://localhost:8080/ and see that we are no longer authenticated.
|
||||
|
||||
@@ -2,15 +2,17 @@
|
||||
Rob Winch, Vedran Pavić
|
||||
:toc:
|
||||
|
||||
This guide describes how to use Spring Session to transparently leverage Redis to back a web application's `HttpSession` when using Spring Boot.
|
||||
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: The completed guide can be found in the <<boot-sample, boot sample application>>.
|
||||
NOTE: You can find the completed guide in the <<boot-sample, boot sample application>>.
|
||||
|
||||
== Updating Dependencies
|
||||
Before you use Spring Session, you must ensure to update your dependencies.
|
||||
We assume you are working with a working Spring Boot web application.
|
||||
If you are using Maven, ensure to add the following dependencies:
|
||||
|
||||
Before you use Spring Session, you must ensure your dependencies.
|
||||
We assume you are working with a working Spring Boot web application.
|
||||
If you are using Maven, you must add the following dependencies:
|
||||
|
||||
====
|
||||
.pom.xml
|
||||
[source,xml]
|
||||
[subs="verbatim,attributes"]
|
||||
@@ -24,114 +26,131 @@ If you are using Maven, ensure to add the following dependencies:
|
||||
</dependency>
|
||||
</dependencies>
|
||||
----
|
||||
====
|
||||
|
||||
Spring Boot provides dependency management for Spring Session modules, so there's no need to explicitly declare dependency version.
|
||||
Spring Boot provides dependency management for Spring Session modules, so you need not explicitly declare dependency version.
|
||||
|
||||
[[boot-spring-configuration]]
|
||||
== Spring Boot Configuration
|
||||
|
||||
After adding the required dependencies, we can create our Spring Boot configuration.
|
||||
Thanks to first-class auto configuration support, setting up Spring Session backed by Redis is as simple as adding a single configuration property to your `application.properties`:
|
||||
Thanks to first-class auto configuration support, setting up Spring Session backed by Redis is as simple as adding a single configuration property to your `application.properties`, as the following listing shows:
|
||||
|
||||
====
|
||||
.src/main/resources/application.properties
|
||||
----
|
||||
spring.session.store-type=redis # Session store type.
|
||||
----
|
||||
====
|
||||
|
||||
Under the hood, Spring Boot will apply configuration that is equivalent to manually adding `@EnableRedisHttpSession` annotation.
|
||||
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.
|
||||
Under the hood, Spring Boot applies configuration that is equivalent to manually adding `@EnableRedisHttpSession` annotation.
|
||||
This creates a Spring bean with the name of `springSessionRepositoryFilter` that implements `Filter`.
|
||||
The filter is in charge of replacing the `HttpSession` implementation to be backed by Spring Session.
|
||||
|
||||
Further customization is possible using `application.properties`:
|
||||
Further customization is possible by using `application.properties`, as the following listing shows:
|
||||
|
||||
====
|
||||
.src/main/resources/application.properties
|
||||
----
|
||||
server.servlet.session.timeout= # Session timeout. If a duration suffix is not specified, seconds will be used.
|
||||
server.servlet.session.timeout= # Session timeout. If a duration suffix is not specified, seconds is used.
|
||||
spring.session.redis.flush-mode=on-save # Sessions flush mode.
|
||||
spring.session.redis.namespace=spring:session # Namespace for keys used to store sessions.
|
||||
----
|
||||
====
|
||||
|
||||
For more information, refer to https://docs.spring.io/spring-boot/docs/{spring-boot-version}/reference/htmlsingle/#boot-features-session[Spring Session] portion of the Spring Boot documentation.
|
||||
For more information, see the https://docs.spring.io/spring-boot/docs/{spring-boot-version}/reference/htmlsingle/#boot-features-session[Spring Session] portion of the Spring Boot documentation.
|
||||
|
||||
[[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*
|
||||
In a production environment, you need 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
|
||||
----
|
||||
spring.redis.host=localhost # Redis server host.
|
||||
spring.redis.password= # Login password of the redis server.
|
||||
spring.redis.port=6379 # Redis server port.
|
||||
----
|
||||
====
|
||||
|
||||
For more information, refer to https://docs.spring.io/spring-boot/docs/{spring-boot-version}/reference/htmlsingle/#boot-features-connecting-to-redis[Connecting to Redis] portion of the Spring Boot documentation.
|
||||
For more information, see the https://docs.spring.io/spring-boot/docs/{spring-boot-version}/reference/htmlsingle/#boot-features-connecting-to-redis[Connecting to Redis] portion of the Spring Boot documentation.
|
||||
|
||||
[[boot-servlet-configuration]]
|
||||
== Servlet Container Initialization
|
||||
|
||||
Our <<boot-spring-configuration,Spring Boot Configuration>> created a Spring Bean named `springSessionRepositoryFilter` that implements `Filter`.
|
||||
Our <<boot-spring-configuration,Spring Boot 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.
|
||||
Last we need to ensure that our Servlet Container (i.e. Tomcat) uses our `springSessionRepositoryFilter` for every request.
|
||||
Last, we need to ensure that our servlet container (that is, Tomcat) uses our `springSessionRepositoryFilter` for every request.
|
||||
Fortunately, Spring Boot takes care of both of these steps for us.
|
||||
|
||||
[[boot-sample]]
|
||||
== Boot Sample Application
|
||||
|
||||
The Boot Sample Application demonstrates how to use Spring Session to transparently leverage Redis to back a web application's `HttpSession` when using Spring Boot.
|
||||
The Boot Sample Application demonstrates how to use Spring Session to transparently leverage Redis to back a web application's `HttpSession` when you use Spring Boot.
|
||||
|
||||
[[boot-running]]
|
||||
=== Running the Boot Sample Application
|
||||
|
||||
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 https://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
|
||||
Alternatively, you can update the `RedisConnectionFactory` to point to a Redis server.
|
||||
Another option is to use https://www.docker.com/[Docker] to run Redis on localhost. See https://hub.docker.com/_/redis/[Docker Redis repository] for detailed instructions.
|
||||
====
|
||||
|
||||
----
|
||||
$ ./gradlew :spring-session-sample-boot-redis:bootRun
|
||||
----
|
||||
====
|
||||
|
||||
NOTE: For the sample to work, you must https://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
|
||||
Alternatively, you can update the `RedisConnectionFactory` to point to a Redis server.
|
||||
Another option is to use https://www.docker.com/[Docker] to run Redis on localhost. See https://hub.docker.com/_/redis/[Docker Redis repository] for detailed instructions.
|
||||
|
||||
You should now be able to access the application at http://localhost:8080/
|
||||
|
||||
[[boot-explore]]
|
||||
=== Exploring the security Sample Application
|
||||
=== Exploring the `security` Sample Application
|
||||
|
||||
Try using the application. Enter the following to log in:
|
||||
Now you can try using the application. Enter the following to log in:
|
||||
|
||||
* **Username** _user_
|
||||
* **Password** _password_
|
||||
* *Username* _user_
|
||||
* *Password* _password_
|
||||
|
||||
Now click the **Login** button.
|
||||
Now click the *Login* button.
|
||||
You should now see a message indicating your are logged in with the user entered previously.
|
||||
The user's information is stored in Redis rather than Tomcat's `HttpSession` implementation.
|
||||
|
||||
[[boot-how]]
|
||||
=== How does it work?
|
||||
=== How Does It Work?
|
||||
|
||||
Instead of using Tomcat's `HttpSession`, we are actually persisting the values in Redis.
|
||||
Instead of using Tomcat's `HttpSession`, we persist the values in Redis.
|
||||
Spring Session replaces the `HttpSession` with an implementation that is backed by Redis.
|
||||
When Spring Security's `SecurityContextPersistenceFilter` saves the `SecurityContext` to the `HttpSession` it is then persisted into Redis.
|
||||
When Spring Security's `SecurityContextPersistenceFilter` saves the `SecurityContext` to the `HttpSession`, it is then persisted into Redis.
|
||||
|
||||
When a new `HttpSession` is created, Spring Session creates a cookie named SESSION in your browser that contains the id of your session.
|
||||
Go ahead and view the cookies (click for help with https://developers.google.com/web/tools/chrome-devtools/manage-data/cookies[Chrome] or https://developer.mozilla.org/en-US/docs/Tools/Storage_Inspector[Firefox]).
|
||||
When a new `HttpSession` is created, Spring Session creates a cookie named `SESSION` in your browser.
|
||||
That cookie contains the ID of your session.
|
||||
You can view the cookies (with https://developers.google.com/web/tools/chrome-devtools/manage-data/cookies[Chrome] or https://developer.mozilla.org/en-US/docs/Tools/Storage_Inspector[Firefox]).
|
||||
|
||||
If you like, you can easily remove the session using redis-cli. For example, on a Linux based system you can type:
|
||||
You can remove the session by using redis-cli.
|
||||
For example, on a Linux based system you can type the following:
|
||||
|
||||
====
|
||||
----
|
||||
$ redis-cli keys '*' | xargs redis-cli del
|
||||
----
|
||||
====
|
||||
|
||||
TIP: The Redis documentation has instructions for https://redis.io/topics/quickstart[installing redis-cli].
|
||||
|
||||
Alternatively, you can also delete the explicit key. Enter the following into your terminal ensuring to replace `7e8383a4-082c-4ffe-a4bc-c40fd3363c5e` with the value of your SESSION cookie:
|
||||
Alternatively, you can also delete the explicit key.
|
||||
To do so, enter the following into your terminal, being sure to replace `7e8383a4-082c-4ffe-a4bc-c40fd3363c5e` with the value of your `SESSION` cookie:
|
||||
|
||||
====
|
||||
----
|
||||
$ redis-cli del spring:session:sessions:7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
|
||||
----
|
||||
=====
|
||||
|
||||
Now visit the application at http://localhost:8080/ and observe that we are no longer authenticated.
|
||||
Now you can visit the application at http://localhost:8080/ and observe that we are no longer authenticated.
|
||||
|
||||
@@ -7,9 +7,8 @@ This guide describes how to use Spring Session to ensure that WebSocket messages
|
||||
|
||||
// tag::disclaimer[]
|
||||
|
||||
NOTE: Spring Session's WebSocket support only works with Spring's WebSocket support.
|
||||
Specifically it does not work with using https://www.jcp.org/en/jsr/detail?id=356[JSR-356] directly.
|
||||
This is due to the fact that JSR-356 does not have a mechanism for intercepting incoming WebSocket messages.
|
||||
NOTE: Spring Session's WebSocket support works only with Spring's WebSocket support.
|
||||
Specifically,it does not work with using https://www.jcp.org/en/jsr/detail?id=356[JSR-356] directly, because JSR-356 does not have a mechanism for intercepting incoming WebSocket messages.
|
||||
|
||||
// end::disclaimer[]
|
||||
|
||||
@@ -17,24 +16,27 @@ This is due to the fact that JSR-356 does not have a mechanism for intercepting
|
||||
|
||||
The first step is to integrate Spring Session with the HttpSession. These steps are already outlined in the link:httpsession.html[HttpSession Guide].
|
||||
|
||||
Please make sure you have already integrated Spring Session with the HttpSession before proceeding.
|
||||
Please make sure you have already integrated Spring Session with HttpSession before proceeding.
|
||||
|
||||
// tag::config[]
|
||||
|
||||
[[websocket-spring-configuration]]
|
||||
== Spring Configuration
|
||||
|
||||
In a typical Spring WebSocket application users would implement `WebSocketMessageBrokerConfigurer`.
|
||||
In a typical Spring WebSocket application, you would implement `WebSocketMessageBrokerConfigurer`.
|
||||
For example, the configuration might look something like the following:
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
include::{websocketdoc-test-dir}WebSocketConfig.java[tags=class]
|
||||
----
|
||||
====
|
||||
|
||||
We can easily update our configuration to use Spring Session's WebSocket support.
|
||||
For example:
|
||||
We can update our configuration to use Spring Session's WebSocket support.
|
||||
The following example shows how to do so:
|
||||
|
||||
====
|
||||
.src/main/java/samples/config/WebSocketConfig.java
|
||||
[source,java]
|
||||
----
|
||||
@@ -43,8 +45,9 @@ include::{samples-dir}boot/websocket/src/main/java/sample/config/WebSocketConfig
|
||||
|
||||
To hook in the Spring Session support we only need to change two things:
|
||||
|
||||
<1> Instead of implementing `WebSocketMessageBrokerConfigurer` we extend `AbstractSessionWebSocketMessageBrokerConfigurer`
|
||||
<1> Instead of implementing `WebSocketMessageBrokerConfigurer`, we extend `AbstractSessionWebSocketMessageBrokerConfigurer`
|
||||
<2> We rename the `registerStompEndpoints` method to `configureStompEndpoints`
|
||||
====
|
||||
|
||||
What does `AbstractSessionWebSocketMessageBrokerConfigurer` do behind the scenes?
|
||||
|
||||
@@ -52,87 +55,89 @@ What does `AbstractSessionWebSocketMessageBrokerConfigurer` do behind the scenes
|
||||
This ensures a custom `SessionConnectEvent` is fired that contains the `WebSocketSession`.
|
||||
The `WebSocketSession` is necessary to terminate any WebSocket connections that are still open when a Spring Session is terminated.
|
||||
* `SessionRepositoryMessageInterceptor` is added as a `HandshakeInterceptor` to every `StompWebSocketEndpointRegistration`.
|
||||
This ensures that the Session is added to the WebSocket properties to enable updating the last accessed time.
|
||||
This ensures that the `Session` is added to the WebSocket properties to enable updating the last accessed time.
|
||||
* `SessionRepositoryMessageInterceptor` is added as a `ChannelInterceptor` to our inbound `ChannelRegistration`.
|
||||
This ensures that every time an inbound message is received, that the last accessed time of our Spring Session is updated.
|
||||
* `WebSocketRegistryListener` is created as a Spring Bean.
|
||||
This ensures that we have a mapping of all of the Session id to the corresponding WebSocket connections.
|
||||
* `WebSocketRegistryListener` is created as a Spring bean.
|
||||
This ensures that we have a mapping of all of the `Session` IDs to the corresponding WebSocket connections.
|
||||
By maintaining this mapping, we can close all the WebSocket connections when a Spring Session (HttpSession) is terminated.
|
||||
|
||||
|
||||
// end::config[]
|
||||
|
||||
[[websocket-sample]]
|
||||
== websocket Sample Application
|
||||
== `websocket` Sample Application
|
||||
|
||||
The websocket sample application demonstrates how to use Spring Session with WebSockets.
|
||||
The `websocket` sample application demonstrates how to use Spring Session with WebSockets.
|
||||
|
||||
=== Running the websocket Sample Application
|
||||
=== Running the `websocket` Sample Application
|
||||
|
||||
You can run the sample by obtaining the {download-url}[source code] and invoking the following command:
|
||||
|
||||
[TIP]
|
||||
====
|
||||
For the purposes of testing session expiration, you may want to change the session expiration to be 1 minute (default is 30 minutes) by adding the following configuration property starting before the application:
|
||||
----
|
||||
$ ./gradlew :spring-session-sample-boot-websocket:bootRun
|
||||
----
|
||||
====
|
||||
|
||||
[TIP]
|
||||
=====
|
||||
For the purposes of testing session expiration, you may want to change the session expiration to be 1 minute (the default is 30 minutes) by adding the following configuration property before starting the application:
|
||||
|
||||
====
|
||||
.src/main/resources/application.properties
|
||||
----
|
||||
server.servlet.session.timeout=1m # Session timeout. If a duration suffix is not specified, seconds will be used.
|
||||
----
|
||||
====
|
||||
=====
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
For the sample to work, you must https://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
|
||||
NOTE: For the sample to work, you must https://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
|
||||
Alternatively, you can update the `RedisConnectionFactory` to point to a Redis server.
|
||||
Another option is to use https://www.docker.com/[Docker] to run Redis on localhost. See https://hub.docker.com/_/redis/[Docker Redis repository] for detailed instructions.
|
||||
====
|
||||
|
||||
----
|
||||
$ ./gradlew :spring-session-sample-boot-websocket:bootRun
|
||||
----
|
||||
Another option is to use https://www.docker.com/[Docker] to run Redis on localhost.
|
||||
See https://hub.docker.com/_/redis/[Docker Redis repository] for detailed instructions.
|
||||
|
||||
You should now be able to access the application at http://localhost:8080/
|
||||
|
||||
=== Exploring the websocket Sample Application
|
||||
=== Exploring the `websocket` Sample Application
|
||||
|
||||
Try using the application. Authenticate with the following information:
|
||||
Now you can try using the application. Authenticate with the following information:
|
||||
|
||||
* **Username** _rob_
|
||||
* **Password** _password_
|
||||
* *Username* _rob_
|
||||
* *Password* _password_
|
||||
|
||||
Now click the **Login** button. You should now be authenticated as the user **rob**.
|
||||
Now click the *Login* button. You should now be authenticated as the user **rob**.
|
||||
|
||||
Open an incognito window and access http://localhost:8080/
|
||||
|
||||
You will be prompted with a log in form. Authenticate with the following information:
|
||||
You are prompted with a login form. Authenticate with the following information:
|
||||
|
||||
* **Username** _luke_
|
||||
* **Password** _password_
|
||||
* *Username* _luke_
|
||||
* *Password* _password_
|
||||
|
||||
Now send a message from *rob* to *luke*. The message should appear.
|
||||
Now send a message from rob to luke. The message should appear.
|
||||
|
||||
Wait for two minutes and try sending a message from *rob* to *luke* again.
|
||||
You will see that the message is no longer sent.
|
||||
Wait for two minutes and try sending a message from rob to luke again.
|
||||
You can see that the message is no longer sent.
|
||||
|
||||
[NOTE]
|
||||
.Why two minutes?
|
||||
====
|
||||
Spring Session will expire in 60 seconds, but the notification from Redis is not guaranteed to happen within 60 seconds.
|
||||
Spring Session expires in 60 seconds, but the notification from Redis is not guaranteed to happen within 60 seconds.
|
||||
To ensure the socket is closed in a reasonable amount of time, Spring Session runs a background task every minute at 00 seconds that forcibly cleans up any expired sessions.
|
||||
This means you will need to wait at most two minutes before the WebSocket connection is terminated.
|
||||
This means you need to wait at most two minutes before the WebSocket connection is terminated.
|
||||
====
|
||||
|
||||
Try accessing http://localhost:8080/
|
||||
You will be prompted to authenticate again.
|
||||
You can now try accessing http://localhost:8080/
|
||||
You are prompted to authenticate again.
|
||||
This demonstrates that the session properly expires.
|
||||
|
||||
Now repeat the same exercise, but instead of waiting two minutes send a message from *each* of the users every 30 seconds.
|
||||
You will see that the messages continue to be sent.
|
||||
Now repeat the same exercise, but instead of waiting two minutes, send a message from each of the users every 30 seconds.
|
||||
You can see that the messages continue to be sent.
|
||||
Try accessing http://localhost:8080/
|
||||
You will not be prompted to authenticate again.
|
||||
You are not prompted to authenticate again.
|
||||
This demonstrates the session is kept alive.
|
||||
|
||||
NOTE: Only messages sent from a user keep the session alive.
|
||||
This is because only messages coming from a user imply user activity.
|
||||
Messages received do not imply activity and thus do not renew the session expiration.
|
||||
Received messages do not imply activity and, thus, do not renew the session expiration.
|
||||
|
||||
@@ -2,17 +2,19 @@
|
||||
Eric Helgeson
|
||||
:toc:
|
||||
|
||||
This guide describes how to use Spring Session to transparently leverage Redis to back a web application's `HttpSession` when using Grails 3.1
|
||||
This guide describes how to use Spring Session to transparently leverage Redis to back a web application's `HttpSession` when you use Grails 3.1
|
||||
|
||||
NOTE: Grails 3.1 is based off spring boot 1.3 so much of the advanced configuration and options can be found in the boot docs as well.
|
||||
NOTE: Grails 3.1 is based off spring boot 1.3, so much of the advanced configuration and options can be found in the Boot docs as well.
|
||||
|
||||
NOTE: The completed guide can be found in the <<grails3-sample, Grails 3 sample application>>.
|
||||
NOTE: You can find the completed guid in the <<grails3-sample, Grails 3 sample application>>.
|
||||
|
||||
== Updating Dependencies
|
||||
Before you use Spring Session, you must ensure to update your dependencies.
|
||||
We assume you are working with a working Grails 3.1 web profile.
|
||||
Add the following dependencies:
|
||||
|
||||
Before you use Spring Session, you must update your dependencies.
|
||||
We assume you are working with a working Grails 3.1 web profile.
|
||||
You must add the following dependencies:
|
||||
|
||||
====
|
||||
.build.gradle
|
||||
[source,groovy]
|
||||
[subs="verbatim,attributes"]
|
||||
@@ -22,11 +24,13 @@ dependencies {
|
||||
compile 'org.springframework.session:spring-session:{spring-session-version}'
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
ifeval::["{version-snapshot}" == "true"]
|
||||
Since We are using a SNAPSHOT version, we need to ensure to add the Spring Snapshot Maven Repository.
|
||||
Ensure you have the following in your pom.xml:
|
||||
Since we use a SNAPSHOT version, we need to ensure to add the Spring Snapshot Maven Repository.
|
||||
You must have the following in your build.gradle:
|
||||
|
||||
====
|
||||
.build.gradle
|
||||
[source,groovy]
|
||||
----
|
||||
@@ -36,12 +40,14 @@ repositories {
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
endif::[]
|
||||
|
||||
ifeval::["{version-milestone}" == "true"]
|
||||
Since We are using a Milestone version, we need to ensure to add the Spring Milestone Maven Repository.
|
||||
Ensure you have the following in your pom.xml:
|
||||
Since we use a Milestone version, we need to add the Spring Milestone Maven Repository.
|
||||
You must have the following in your build.gradle:
|
||||
|
||||
====
|
||||
.build.gradle
|
||||
[source,groovy]
|
||||
----
|
||||
@@ -51,6 +57,7 @@ repositories {
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
endif::[]
|
||||
|
||||
[[grails3-redis-configuration]]
|
||||
@@ -58,8 +65,9 @@ endif::[]
|
||||
|
||||
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.yml*
|
||||
For example, you can include the following in your application.yml:
|
||||
|
||||
====
|
||||
.grails-app/conf/application.yml
|
||||
[source,yml]
|
||||
----
|
||||
@@ -69,8 +77,9 @@ spring:
|
||||
password: secret
|
||||
port: 6397
|
||||
----
|
||||
====
|
||||
|
||||
For more information, refer to https://docs.spring.io/spring-boot/docs/{spring-boot-version}/reference/htmlsingle/#boot-features-connecting-to-redis[Connecting to Redis] portion of the Spring Boot documentation.
|
||||
For more information, see the https://docs.spring.io/spring-boot/docs/{spring-boot-version}/reference/htmlsingle/#boot-features-connecting-to-redis[Connecting to Redis] portion of the Spring Boot documentation.
|
||||
|
||||
[[grails3-sample]]
|
||||
== Grails 3 Sample Application
|
||||
@@ -82,52 +91,61 @@ The Grails 3 Sample Application demonstrates how to use Spring Session to transp
|
||||
|
||||
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 https://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
|
||||
Alternatively, you can update the `RedisConnectionFactory` to point to a Redis server.
|
||||
Another option is to use https://www.docker.com/[Docker] to run Redis on localhost. See https://hub.docker.com/_/redis/[Docker Redis repository] for detailed instructions.
|
||||
====
|
||||
|
||||
----
|
||||
$ ./gradlew :spring-session-sample-misc-grails3:bootRun
|
||||
----
|
||||
|
||||
NOTE:For the sample to work, you must https://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
|
||||
Alternatively, you can update the `RedisConnectionFactory` to point to a Redis server.
|
||||
Another option is to use https://www.docker.com/[Docker] to run Redis on localhost.
|
||||
See https://hub.docker.com/_/redis/[Docker Redis repository] for detailed instructions.
|
||||
|
||||
You should now be able to access the application at http://localhost:8080/test/index
|
||||
|
||||
[[grails3-explore]]
|
||||
=== Exploring the security Sample Application
|
||||
=== Exploring the `security` Sample Application
|
||||
|
||||
Try using the application. Enter the following to log in:
|
||||
You can now try using the application. Enter the following to log in:
|
||||
|
||||
* **Username** _user_
|
||||
* **Password** _password_
|
||||
* *Username* _user_
|
||||
* *Password* _password_
|
||||
|
||||
Now click the **Login** button.
|
||||
You should now see a message indicating your are logged in with the user entered previously.
|
||||
Now click the *Login* button.
|
||||
You should now see a message indicating that your are logged in with the user entered previously.
|
||||
The user's information is stored in Redis rather than Tomcat's `HttpSession` implementation.
|
||||
|
||||
[[grails3-how]]
|
||||
=== How does it work?
|
||||
=== How Does It Work?
|
||||
|
||||
Instead of using Tomcat's `HttpSession`, we are actually persisting the values in Redis.
|
||||
Instead of using Tomcat's `HttpSession`, we persist the values in Redis.
|
||||
Spring Session replaces the `HttpSession` with an implementation that is backed by Redis.
|
||||
When Spring Security's `SecurityContextPersistenceFilter` saves the `SecurityContext` to the `HttpSession` it is then persisted into Redis.
|
||||
When Spring Security's `SecurityContextPersistenceFilter` saves the `SecurityContext` to the `HttpSession`, it is then persisted into Redis.
|
||||
|
||||
When a new `HttpSession` is created, Spring Session creates a cookie named SESSION in your browser that contains the id of your session.
|
||||
Go ahead and view the cookies (click for help with https://developers.google.com/web/tools/chrome-devtools/manage-data/cookies[Chrome] or https://developer.mozilla.org/en-US/docs/Tools/Storage_Inspector[Firefox]).
|
||||
When a new `HttpSession` is created, Spring Session creates a cookie named `SESSION` in your browser.
|
||||
That cookie contains the ID of your session.
|
||||
You can view the cookies (with https://developers.google.com/web/tools/chrome-devtools/manage-data/cookies[Chrome] or https://developer.mozilla.org/en-US/docs/Tools/Storage_Inspector[Firefox]).
|
||||
|
||||
If you like, you can easily remove the session using redis-cli. For example, on a Linux based system you can type:
|
||||
You can remove the session by using redis-cli.
|
||||
For example, on a Linux based system you can type the following:
|
||||
|
||||
====
|
||||
----
|
||||
$ redis-cli keys '*' | xargs redis-cli del
|
||||
----
|
||||
====
|
||||
|
||||
TIP: The Redis documentation has instructions for https://redis.io/topics/quickstart[installing redis-cli].
|
||||
|
||||
Alternatively, you can also delete the explicit key. Enter the following into your terminal ensuring to replace `7e8383a4-082c-4ffe-a4bc-c40fd3363c5e` with the value of your SESSION cookie:
|
||||
Alternatively, you can also delete the explicit key.
|
||||
To do so, enter the following into your terminal, being sure to replace `7e8383a4-082c-4ffe-a4bc-c40fd3363c5e` with the value of your `SESSION` cookie:
|
||||
|
||||
====
|
||||
----
|
||||
$ redis-cli del spring:session:sessions:7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
|
||||
----
|
||||
====
|
||||
|
||||
Now visit the application at http://localhost:8080/test/index and observe that we are no longer authenticated.
|
||||
Now you can visit the application at http://localhost:8080/test/index and see that we are no longer authenticated.
|
||||
|
||||
NOTE: Spring Session will not work with grails flash scope without additional work. +
|
||||
See this answer for an explanation: https://stackoverflow.com/a/43311427
|
||||
NOTE: Spring Session does not work with Grails flash scope without additional work.
|
||||
See https://stackoverflow.com/a/43311427 for an explanation.
|
||||
|
||||
@@ -3,100 +3,95 @@ Rob Winch
|
||||
: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[setup Spring Session in your project].
|
||||
The guide assumes you have already link:./httpsession.html[set up Spring Session in your project].
|
||||
|
||||
NOTE: The completed guide can be found in the <<custom-cookie-sample, Custom Cookie sample application>>.
|
||||
NOTE: You can find the completed guide in the <<custom-cookie-sample, Custom Cookie sample application>>.
|
||||
|
||||
[[custom-cookie-spring-configuration]]
|
||||
== Spring Java Configuration
|
||||
|
||||
Once you have setup Spring Session you can easily customize how the session cookie is written by exposing a `CookieSerializer` as a Spring Bean.
|
||||
Out of the box, Spring Session comes with `DefaultCookieSerializer`.
|
||||
Simply exposing the `DefaultCookieSerializer` as a Spring Bean will augment the existing configuration when using configurations like `@EnableRedisHttpSession`.
|
||||
You can find an example of customizing Spring Session's cookie below:
|
||||
Once you have set up Spring Session, you can customize how the session cookie is written by exposing a `CookieSerializer` as a Spring bean.
|
||||
Spring Session comes with `DefaultCookieSerializer`.
|
||||
Exposing the `DefaultCookieSerializer` as a Spring bean augments the existing configuration when you use configurations like `@EnableRedisHttpSession`.
|
||||
The following example shows how to customize Spring Session's cookie:
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
include::{samples-dir}javaconfig/custom-cookie/src/main/java/sample/Config.java[tags=cookie-serializer]
|
||||
----
|
||||
|
||||
<1> We customize the name of the cookie to be JSESSIONID
|
||||
<2> We customize the path of the cookie to be "/" (rather than the default of the context root)
|
||||
<3> We customize the domain name pattern (a regular expression) to be `^.+?\\.(\\w+\\.[a-z]+)$`
|
||||
<1> We customize the name of the cookie to be `JSESSIONID`.
|
||||
<2> We customize the path of the cookie to be `/` (rather than the default of the context root).
|
||||
<3> We customize the domain name pattern (a regular expression) to be `^.+?\\.(\\w+\\.[a-z]+)$`.
|
||||
This allows sharing a session across domains and applications.
|
||||
If the regular expression does not match, no domain is set and the existing domain will be used.
|
||||
If the regular expression matches, the first https://docs.oracle.com/javase/tutorial/essential/regex/groups.html[grouping] will be used as the domain.
|
||||
This means that a request to https://child.example.com will set the domain to example.com.
|
||||
However, a request to http://localhost:8080/ or http://192.168.1.100:8080/ will leave the cookie unset and thus still work in development without any changes necessary for production.
|
||||
If the regular expression does not match, no domain is set and the existing domain is used.
|
||||
If the regular expression matches, the first https://docs.oracle.com/javase/tutorial/essential/regex/groups.html[grouping] is used as the domain.
|
||||
This means that a request to https://child.example.com sets the domain to `example.com`.
|
||||
However, a request to http://localhost:8080/ or https://192.168.1.100:8080/ leaves the cookie unset and, thus, still works in development without any changes being necessary for production.
|
||||
====
|
||||
|
||||
[WARNING]
|
||||
====
|
||||
It is important to note that users should only match on valid domain characters since the domain name is reflected in the response.
|
||||
This is prevent a malicious user from performing attacks like https://en.wikipedia.org/wiki/HTTP_response_splitting[HTTP Response Splitting].
|
||||
====
|
||||
WARNING: You should only match on valid domain characters, since the domain name is reflected in the response.
|
||||
Doing so prevents a malicious user from performing such attacks as https://en.wikipedia.org/wiki/HTTP_response_splitting[HTTP Response Splitting].
|
||||
|
||||
[[custom-cookie-options]]
|
||||
== Configuration Options
|
||||
|
||||
The configuration options available are:
|
||||
The following configuration options are available:
|
||||
|
||||
* `cookieName` - the name of the cookie to use
|
||||
Default "SESSION"
|
||||
* `useSecureCookie` - specify if a secure cookie be used
|
||||
Default use value of `HttpServletRequest.isSecure()` at the time of creation.
|
||||
* `cookiePath` - the path of the cookie
|
||||
Default is context root
|
||||
* `cookieMaxAge` - specifies the max age of the cookie to be set at the time the session is created.
|
||||
Default is -1 which indicates the cookie will be removed when the browser is closed.
|
||||
* `jvmRoute` - specifies a suffix to be appended to the session id and included in the cookie.
|
||||
* `cookieName`: The name of the cookie to use.
|
||||
Default: `SESSION`.
|
||||
* `useSecureCookie`: Specifies whether a secure cookie should be used.
|
||||
Default: Use the value of `HttpServletRequest.isSecure()` at the time of creation.
|
||||
* `cookiePath`: The path of the cookie.
|
||||
Default: The context root.
|
||||
* `cookieMaxAge`: Specifies the max age of the cookie to be set at the time the session is created.
|
||||
Default: `-1`, which indicates the cookie should be removed when the browser is closed.
|
||||
* `jvmRoute`: Specifies a suffix to be appended to the session ID and included in the cookie.
|
||||
Used to identify which JVM to route to for session affinity.
|
||||
With some implementations (i.e. Redis) this provides no performance benefit.
|
||||
However, this can help with tracing logs of a particular user.
|
||||
* `domainName` - allows specifying a specific domain name to be used for the cookie.
|
||||
This option is simple to understand, but will likely require a different configuration between development and production environments.
|
||||
See domainNamePattern as an alternative.
|
||||
* `domainNamePattern` - a case insensitive pattern used to extract the domain name from the `HttpServletRequest#getServerName()`.
|
||||
The pattern should provide a single grouping used to extract the value of the cookie domain.
|
||||
If the regular expression does not match, no domain is set and the existing domain will be used.
|
||||
If the regular expression matches, the first https://docs.oracle.com/javase/tutorial/essential/regex/groups.html[grouping] will be used as the domain.
|
||||
With some implementations (that is, Redis) this option provides no performance benefit.
|
||||
However, it can help with tracing logs of a particular user.
|
||||
* `domainName`: Allows specifying a specific domain name to be used for the cookie.
|
||||
This option is simple to understand but often requires a different configuration between development and production environments.
|
||||
See `domainNamePattern` as an alternative.
|
||||
* `domainNamePattern`: A case-insensitive pattern used to extract the domain name from the `HttpServletRequest#getServerName()`.
|
||||
The pattern should provide a single grouping that is used to extract the value of the cookie domain.
|
||||
If the regular expression does not match, no domain is set and the existing domain is used.
|
||||
If the regular expression matches, the first https://docs.oracle.com/javase/tutorial/essential/regex/groups.html[grouping] is used as the domain.
|
||||
|
||||
[WARNING]
|
||||
====
|
||||
It is important to note that users should only match on valid domain characters since the domain name is reflected in the response.
|
||||
This is prevent a malicious user from performing attacks like https://en.wikipedia.org/wiki/HTTP_response_splitting[HTTP Response Splitting].
|
||||
====
|
||||
WARNING: You should only match on valid domain characters, since the domain name is reflected in the response.
|
||||
Doing so prevents a malicious user from performing such attacks as https://en.wikipedia.org/wiki/HTTP_response_splitting[HTTP Response Splitting].
|
||||
|
||||
|
||||
[[custom-cookie-sample]]
|
||||
== custom-cookie Sample Application
|
||||
== `custom-cookie` Sample Application
|
||||
|
||||
This section describes how to work with the `custom-cookie` sample application.
|
||||
|
||||
|
||||
=== Running the custom-cookie Sample Application
|
||||
=== Running the `custom-cookie` Sample Application
|
||||
|
||||
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 https://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
|
||||
Alternatively, you can update the `RedisConnectionFactory` to point to a Redis server.
|
||||
Another option is to use https://www.docker.com/[Docker] to run Redis on localhost. See https://hub.docker.com/_/redis/[Docker Redis repository] for detailed instructions.
|
||||
====
|
||||
|
||||
----
|
||||
$ ./gradlew :spring-session-sample-javaconfig-custom-cookie:tomcatRun
|
||||
----
|
||||
====
|
||||
|
||||
NOTE: For the sample to work, you must https://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
|
||||
Alternatively, you can update the `RedisConnectionFactory` to point to a Redis server.
|
||||
Another option is to use https://www.docker.com/[Docker] to run Redis on localhost. See https://hub.docker.com/_/redis/[Docker Redis repository] for detailed instructions.
|
||||
|
||||
You should now be able to access the application at http://localhost:8080/
|
||||
|
||||
=== Exploring the custom-cookie Sample Application
|
||||
=== Exploring the `custom-cookie` Sample Application
|
||||
|
||||
Try using the application. Fill out the form with the following information:
|
||||
Now you can use the application. Fill out the form with the following information:
|
||||
|
||||
* **Attribute Name:** _username_
|
||||
* **Attribute Value:** _rob_
|
||||
* *Attribute Name:* _username_
|
||||
* *Attribute Value:* _rob_
|
||||
|
||||
Now click the **Set Attribute** button.
|
||||
Now click the *Set Attribute* button.
|
||||
You should now see the values displayed in the table.
|
||||
|
||||
If you look at the cookies for the application, you can see the cookie is saved to the custom name of JSESSIONID
|
||||
If you look at the cookies for the application, you can see the cookie is saved to the custom name of `JSESSIONID`.
|
||||
|
||||
@@ -2,15 +2,17 @@
|
||||
Tommy Ludwig; Rob Winch
|
||||
:toc:
|
||||
|
||||
This guide describes how to use Spring Session along with Spring Security using Hazelcast as your data store.
|
||||
It assumes you have already applied Spring Security to your application.
|
||||
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: The completed guide can be found in the <<hazelcast-spring-security-sample, Hazelcast Spring Security sample application>>.
|
||||
NOTE: You cand find the completed guide in the <<hazelcast-spring-security-sample, Hazelcast Spring Security sample application>>.
|
||||
|
||||
== Updating Dependencies
|
||||
Before you use Spring Session, you must ensure to update your dependencies.
|
||||
If you are using Maven, ensure to add the following dependencies:
|
||||
|
||||
Before you use Spring Session, you must update your dependencies.
|
||||
If you use Maven, you must add the following dependencies:
|
||||
|
||||
====
|
||||
.pom.xml
|
||||
[source,xml]
|
||||
[subs="verbatim,attributes"]
|
||||
@@ -30,11 +32,13 @@ If you are using Maven, ensure to add the following dependencies:
|
||||
</dependency>
|
||||
</dependencies>
|
||||
----
|
||||
====
|
||||
|
||||
ifeval::["{version-snapshot}" == "true"]
|
||||
Since We are using a SNAPSHOT version, we need to ensure to add the Spring Snapshot Maven Repository.
|
||||
Ensure you have the following in your pom.xml:
|
||||
Since we are using a SNAPSHOT version, we need to add the Spring Snapshot Maven Repository.
|
||||
You must have the following in your pom.xml:
|
||||
|
||||
====
|
||||
.pom.xml
|
||||
[source,xml]
|
||||
----
|
||||
@@ -48,12 +52,14 @@ Ensure you have the following in your pom.xml:
|
||||
</repository>
|
||||
</repositories>
|
||||
----
|
||||
====
|
||||
endif::[]
|
||||
|
||||
ifeval::["{version-milestone}" == "true"]
|
||||
Since We are using a Milestone version, we need to ensure to add the Spring Milestone Maven Repository.
|
||||
Ensure you have the following in your pom.xml:
|
||||
Since we are using a Milestone version, we need to add the Spring Milestone Maven Repository.
|
||||
You must have the following in your pom.xml:
|
||||
|
||||
====
|
||||
.pom.xml
|
||||
[source,xml]
|
||||
----
|
||||
@@ -62,6 +68,7 @@ Ensure you have the following in your pom.xml:
|
||||
<url>https://repo.spring.io/libs-milestone</url>
|
||||
</repository>
|
||||
----
|
||||
====
|
||||
endif::[]
|
||||
|
||||
// tag::config[]
|
||||
@@ -70,126 +77,146 @@ endif::[]
|
||||
== Spring Configuration
|
||||
|
||||
After adding the required dependencies, we can create our Spring configuration.
|
||||
The Spring configuration is responsible for creating a Servlet Filter that replaces the `HttpSession` implementation with an implementation backed by Spring Session.
|
||||
Add the following Spring Configuration:
|
||||
The Spring configuration is responsible for creating a servlet filter that replaces the `HttpSession` implementation with an implementation backed by Spring Session.
|
||||
To do so, add the following Spring Configuration:
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
include::{docs-test-dir}docs/http/HazelcastHttpSessionConfig.java[tags=config]
|
||||
----
|
||||
|
||||
<1> The `@EnableHazelcastHttpSession` 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 Hazelcast.
|
||||
<2> In order to support retrieval of sessions by principal name index, appropriate `ValueExtractor` needs to be registered.
|
||||
<1> The `@EnableHazelcastHttpSession` annotation creates a Spring bean named `springSessionRepositoryFilter` that implements `Filter`.
|
||||
The filter is in charge of replacing the `HttpSession` implementation to be backed by Spring Session.
|
||||
In this instance, Spring Session is backed by Hazelcast.
|
||||
<2> In order to support retrieval of sessions by principal name index, an appropriate `ValueExtractor` needs to be registered.
|
||||
Spring Session provides `PrincipalNameExtractor` for this purpose.
|
||||
<3> We create a `HazelcastInstance` that connects Spring Session to Hazelcast.
|
||||
By default, an embedded instance of Hazelcast is started and connected to by the application.
|
||||
For more information on configuring Hazelcast, refer to the http://docs.hazelcast.org/docs/{hazelcast-version}/manual/html-single/index.html#hazelcast-configuration[reference documentation].
|
||||
By default, the application starts and connects to an embedded instance of Hazelcast.
|
||||
For more information on configuring Hazelcast, see the https://docs.hazelcast.org/docs/{hazelcast-version}/manual/html-single/index.html#hazelcast-configuration[reference documentation].
|
||||
====
|
||||
|
||||
== Servlet Container Initialization
|
||||
|
||||
Our <<security-spring-configuration,Spring Configuration>> created a Spring Bean named `springSessionRepositoryFilter` that implements `Filter`.
|
||||
Our <<security-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 `SessionConfig` class.
|
||||
Since our application is already loading Spring configuration using our `SecurityInitializer` class, we can simply add our `SessionConfig` class to it.
|
||||
Since our application is already loading Spring configuration by using our `SecurityInitializer` class, we can add our `SessionConfig` class to it.
|
||||
The following listing shows how to do so:
|
||||
|
||||
====
|
||||
.src/main/java/sample/SecurityInitializer.java
|
||||
[source,java]
|
||||
----
|
||||
include::{samples-dir}javaconfig/hazelcast/src/main/java/sample/SecurityInitializer.java[tags=class]
|
||||
----
|
||||
====
|
||||
|
||||
Last we need to ensure that our Servlet Container (i.e. Tomcat) uses our `springSessionRepositoryFilter` for every request.
|
||||
Last, we need to ensure that our Servlet Container (that is, Tomcat) uses our `springSessionRepositoryFilter` for every request.
|
||||
It is extremely important that Spring Session's `springSessionRepositoryFilter` is invoked before Spring Security's `springSecurityFilterChain`.
|
||||
This ensures that the `HttpSession` that Spring Security uses is backed by Spring Session.
|
||||
Fortunately, Spring Session provides a utility class named `AbstractHttpSessionApplicationInitializer` that makes this extremely easy.
|
||||
You can find an example below:
|
||||
Doing so ensures that the `HttpSession` that Spring Security uses is backed by Spring Session.
|
||||
Fortunately, Spring Session provides a utility class named `AbstractHttpSessionApplicationInitializer` that makes this doing so easy.
|
||||
The following example shows how to do so:
|
||||
|
||||
====
|
||||
.src/main/java/sample/Initializer.java
|
||||
[source,java]
|
||||
----
|
||||
include::{samples-dir}javaconfig/hazelcast/src/main/java/sample/Initializer.java[tags=class]
|
||||
----
|
||||
====
|
||||
|
||||
NOTE: The name of our class (Initializer) does not matter. What is important is that we extend `AbstractHttpSessionApplicationInitializer`.
|
||||
NOTE: The name of our class (`Initializer`) does not matter. What is important is that we extend `AbstractHttpSessionApplicationInitializer`.
|
||||
|
||||
By extending `AbstractHttpSessionApplicationInitializer` we ensure that the Spring Bean by the name `springSessionRepositoryFilter` is registered with our Servlet Container for every request before Spring Security's `springSecurityFilterChain`.
|
||||
By extending `AbstractHttpSessionApplicationInitializer`, we ensure that the Spring Bean named `springSessionRepositoryFilter` is registered with our servlet container for every request before Spring Security's `springSecurityFilterChain`.
|
||||
|
||||
// end::config[]
|
||||
|
||||
[[hazelcast-spring-security-sample]]
|
||||
== Hazelcast Spring Security Sample Application
|
||||
|
||||
This section describes how to work with the Hazelcast Spring Security sample application.
|
||||
|
||||
=== Running the Sample Application
|
||||
|
||||
You can run the sample by obtaining the {download-url}[source code] and invoking the following command:
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
Hazelcast will run in embedded mode with your application by default, but if you want to connect
|
||||
to a stand alone instance instead, you can configure it by following the instructions in the
|
||||
http://docs.hazelcast.org/docs/{hazelcast-version}/manual/html-single/index.html#hazelcast-configuration[reference documentation].
|
||||
====
|
||||
|
||||
----
|
||||
$ ./gradlew :spring-session-sample-javaconfig-hazelcast:tomcatRun
|
||||
----
|
||||
====
|
||||
|
||||
NOTE: By default, Hazelcast runs in embedded mode with your application.
|
||||
However, if you want to connect to a standalone instance instead, you can configure it by following the instructions in the https://docs.hazelcast.org/docs/{hazelcast-version}/manual/html-single/index.html#hazelcast-configuration[reference documentation].
|
||||
|
||||
You should now be able to access the application at http://localhost:8080/
|
||||
|
||||
=== Exploring the security Sample Application
|
||||
=== Exploring the Security Sample Application
|
||||
|
||||
Try using the application. Enter the following to log in:
|
||||
You can now try using the application.
|
||||
To do so, enter the following to log in:
|
||||
|
||||
* **Username** _user_
|
||||
* **Password** _password_
|
||||
* *Username* _user_
|
||||
* *Password* _password_
|
||||
|
||||
Now click the **Login** button.
|
||||
You should now see a message indicating your are logged in with the user entered previously.
|
||||
Now click the *Login* button.
|
||||
You should now see a message indicating that your are logged in with the user entered previously.
|
||||
The user's information is stored in Hazelcast rather than Tomcat's `HttpSession` implementation.
|
||||
|
||||
=== How does it work?
|
||||
=== How Does It Work?
|
||||
|
||||
Instead of using Tomcat's `HttpSession`, we are actually persisting the values in Hazelcast.
|
||||
Instead of using Tomcat's `HttpSession`, we persist the values in Hazelcast.
|
||||
Spring Session replaces the `HttpSession` with an implementation that is backed by a `Map` in Hazelcast.
|
||||
When Spring Security's `SecurityContextPersistenceFilter` saves the `SecurityContext` to the `HttpSession` it is then persisted into Hazelcast.
|
||||
When Spring Security's `SecurityContextPersistenceFilter` saves the `SecurityContext` to the `HttpSession`, it is then persisted into Hazelcast.
|
||||
|
||||
When a new `HttpSession` is created, Spring Session creates a cookie named SESSION in your browser that contains the id of your session.
|
||||
Go ahead and view the cookies (click for help with https://developers.google.com/web/tools/chrome-devtools/manage-data/cookies[Chrome] or https://developer.mozilla.org/en-US/docs/Tools/Storage_Inspector[Firefox]).
|
||||
When a new `HttpSession` is created, Spring Session creates a cookie named `SESSION` in your browser. That cookie contains the ID of your session.
|
||||
You can view the cookies (with https://developers.google.com/web/tools/chrome-devtools/manage-data/cookies[Chrome] or https://developer.mozilla.org/en-US/docs/Tools/Storage_Inspector[Firefox]).
|
||||
|
||||
=== Interact with the data store
|
||||
=== Interacting with the Data Store
|
||||
|
||||
If you like, you can remove the session using http://docs.hazelcast.org/docs/{hazelcast-version}/manual/html-single/index.html#hazelcast-java-client[a Java client],
|
||||
http://docs.hazelcast.org/docs/{hazelcast-version}/manual/html-single/index.html#other-client-implementations[one of the other clients], or the
|
||||
http://docs.hazelcast.org/docs/{hazelcast-version}/manual/html-single/index.html#management-center[management center].
|
||||
You can remove the session by using https://docs.hazelcast.org/docs/{hazelcast-version}/manual/html-single/index.html#hazelcast-java-client[a Java client],
|
||||
https://docs.hazelcast.org/docs/{hazelcast-version}/manual/html-single/index.html#other-client-implementations[one of the other clients], or the
|
||||
https://docs.hazelcast.org/docs/{hazelcast-version}/manual/html-single/index.html#management-center[management center].
|
||||
|
||||
==== Using the console
|
||||
==== Using the Console
|
||||
|
||||
For example, using the management center console after connecting to your Hazelcast node:
|
||||
For example, to remove the session by using the management center console after connecting to your Hazelcast node, run the following commands:
|
||||
|
||||
====
|
||||
----
|
||||
default> ns spring:session:sessions
|
||||
spring:session:sessions> m.clear
|
||||
----
|
||||
====
|
||||
|
||||
TIP: The Hazelcast documentation has instructions for http://docs.hazelcast.org/docs/{hazelcast-version}/manual/html-single/index.html#executing-console-commands[the console].
|
||||
TIP: The Hazelcast documentation has instructions for https://docs.hazelcast.org/docs/{hazelcast-version}/manual/html-single/index.html#executing-console-commands[the console].
|
||||
|
||||
Alternatively, you can also delete the explicit key. Enter the following into the console ensuring to replace `7e8383a4-082c-4ffe-a4bc-c40fd3363c5e` with the value of your SESSION cookie:
|
||||
Alternatively, you can also delete the explicit key. Enter the following into the console, being sure to replace `7e8383a4-082c-4ffe-a4bc-c40fd3363c5e` with the value of your `SESSION` cookie:
|
||||
|
||||
====
|
||||
----
|
||||
spring:session:sessions> m.remove 7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
|
||||
----
|
||||
====
|
||||
|
||||
Now visit the application at http://localhost:8080/ and observe that we are no longer authenticated.
|
||||
|
||||
==== Using the REST API
|
||||
|
||||
As described in the other clients section of the documentation, there is a
|
||||
http://docs.hazelcast.org/docs/{hazelcast-version}/manual/html-single/index.html#rest-client[REST API]
|
||||
As described in the section of the documentation that cover other clients, there is a
|
||||
https://docs.hazelcast.org/docs/{hazelcast-version}/manual/html-single/index.html#rest-client[REST API]
|
||||
provided by the Hazelcast node(s).
|
||||
|
||||
For example, you could delete an individual key as follows (replacing `7e8383a4-082c-4ffe-a4bc-c40fd3363c5e` with the value of your SESSION cookie):
|
||||
For example, you could delete an individual key as follows (being sure to replace `7e8383a4-082c-4ffe-a4bc-c40fd3363c5e` with the value of your SESSION cookie):
|
||||
|
||||
====
|
||||
----
|
||||
$ curl -v -X DELETE http://localhost:xxxxx/hazelcast/rest/maps/spring:session:sessions/7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
|
||||
----
|
||||
====
|
||||
|
||||
TIP: The port number of the Hazelcast node will be printed to the console on startup. Replace `xxxxx` above with the port number.
|
||||
TIP: The port number of the Hazelcast node is printed to the console on startup. Replace `xxxxx` with the port number.
|
||||
|
||||
Now observe that you are no longer authenticated with this session.
|
||||
Now you can see that you are no longer authenticated with this session.
|
||||
|
||||
@@ -4,12 +4,14 @@ Rob Winch, Vedran Pavić
|
||||
|
||||
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: The completed guide can be found in the <<httpsession-jdbc-sample, httpsession-jdbc sample application>>.
|
||||
NOTE: You can find the completed guide in the <<httpsession-jdbc-sample, httpsession-jdbc sample application>>.
|
||||
|
||||
== Updating Dependencies
|
||||
Before you use Spring Session, you must ensure to update your dependencies.
|
||||
If you are using Maven, ensure to add the following dependencies:
|
||||
|
||||
Before you use Spring Session, you must update your dependencies.
|
||||
If you use Maven, you must add the following dependencies:
|
||||
|
||||
====
|
||||
.pom.xml
|
||||
[source,xml]
|
||||
[subs="verbatim,attributes"]
|
||||
@@ -30,11 +32,13 @@ If you are using Maven, ensure to add the following dependencies:
|
||||
</dependency>
|
||||
</dependencies>
|
||||
----
|
||||
====
|
||||
|
||||
ifeval::["{version-snapshot}" == "true"]
|
||||
Since we are using a SNAPSHOT version, we need to ensure to add the Spring Snapshot Maven Repository.
|
||||
Ensure you have the following in your pom.xml:
|
||||
You must have the following in your pom.xml:
|
||||
|
||||
====
|
||||
.pom.xml
|
||||
[source,xml]
|
||||
----
|
||||
@@ -48,12 +52,14 @@ Ensure you have the following in your pom.xml:
|
||||
</repository>
|
||||
</repositories>
|
||||
----
|
||||
====
|
||||
endif::[]
|
||||
|
||||
ifeval::["{version-milestone}" == "true"]
|
||||
Since We are using a Milestone version, we need to ensure to add the Spring Milestone Maven Repository.
|
||||
Ensure you have the following in your pom.xml:
|
||||
Since we are using a Milestone version, we need to add the Spring Milestone Maven Repository.
|
||||
You must have the following in your pom.xml:
|
||||
|
||||
====
|
||||
.pom.xml
|
||||
[source,xml]
|
||||
----
|
||||
@@ -62,6 +68,7 @@ Ensure you have the following in your pom.xml:
|
||||
<url>https://repo.spring.io/libs-milestone</url>
|
||||
</repository>
|
||||
----
|
||||
====
|
||||
endif::[]
|
||||
|
||||
// tag::config[]
|
||||
@@ -71,82 +78,95 @@ endif::[]
|
||||
|
||||
After adding the required dependencies, we can create our Spring configuration.
|
||||
The Spring configuration is responsible for creating a Servlet Filter that replaces the `HttpSession` implementation with an implementation backed by Spring Session.
|
||||
Add the following Spring Configuration:
|
||||
To do so, add the following Spring Configuration:
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
include::{samples-dir}javaconfig/jdbc/src/main/java/sample/Config.java[tags=class]
|
||||
----
|
||||
|
||||
<1> The `@EnableJdbcHttpSession` 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 a relational database.
|
||||
<2> We create a `dataSource` that connects Spring Session to an embedded instance of H2 database.
|
||||
We configure the H2 database to create database tables using the SQL script which is included in Spring Session.
|
||||
<1> The `@EnableJdbcHttpSession` annotation creates a Spring Bean with the name of `springSessionRepositoryFilter`.
|
||||
That bean implements `Filter`.
|
||||
The filter is in charge of replacing the `HttpSession` implementation to be backed by Spring Session.
|
||||
In this instance, Spring Session is backed by a relational database.
|
||||
<2> We create a `dataSource` that connects Spring Session to an embedded instance of an H2 database.
|
||||
We configure the H2 database to create database tables by using the SQL script that is included in Spring Session.
|
||||
<3> We create a `transactionManager` that manages transactions for previously configured `dataSource`.
|
||||
====
|
||||
|
||||
For additional information on how to configure data access related concerns, please refer to the https://docs.spring.io/spring/docs/{spring-framework-version}/spring-framework-reference/data-access.html[Spring Framework Reference Documentation].
|
||||
For additional information on how to configure data access related concerns, see the https://docs.spring.io/spring/docs/{spring-framework-version}/spring-framework-reference/data-access.html[Spring Framework Reference Documentation].
|
||||
|
||||
== Java Servlet Container Initialization
|
||||
|
||||
Our <<httpsession-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.
|
||||
Last we need to ensure that our Servlet Container (i.e. Tomcat) uses our `springSessionRepositoryFilter` for every request.
|
||||
Fortunately, Spring Session provides a utility class named `AbstractHttpSessionApplicationInitializer` both of these steps extremely easy.
|
||||
You can find an example below:
|
||||
Last, we need to ensure that our Servlet Container (that is, Tomcat) uses our `springSessionRepositoryFilter` for every request.
|
||||
Fortunately, Spring Session provides a utility class named `AbstractHttpSessionApplicationInitializer` to make both of these steps easy.
|
||||
The following example shows how to do so:
|
||||
|
||||
====
|
||||
.src/main/java/sample/Initializer.java
|
||||
[source,java]
|
||||
----
|
||||
include::{samples-dir}javaconfig/jdbc/src/main/java/sample/Initializer.java[tags=class]
|
||||
----
|
||||
|
||||
NOTE: The name of our class (Initializer) does not matter. What is important is that we extend `AbstractHttpSessionApplicationInitializer`.
|
||||
NOTE: The name of our class (Initializer) does not matter.
|
||||
What is important is that we extend `AbstractHttpSessionApplicationInitializer`.
|
||||
|
||||
<1> The first step is to extend `AbstractHttpSessionApplicationInitializer`.
|
||||
This ensures that the Spring Bean by the name `springSessionRepositoryFilter` is registered with our Servlet Container for every request.
|
||||
<2> `AbstractHttpSessionApplicationInitializer` also provides a mechanism to easily ensure Spring loads our `Config`.
|
||||
Doing so ensures that the Spring bean named `springSessionRepositoryFilter` is registered with our Servlet Container for every request.
|
||||
<2> `AbstractHttpSessionApplicationInitializer` also provides a mechanism to ensure Spring loads our `Config`.
|
||||
====
|
||||
|
||||
// end::config[]
|
||||
|
||||
[[httpsession-jdbc-sample]]
|
||||
== httpsession-jdbc Sample Application
|
||||
== `httpsession-jdbc` Sample Application
|
||||
|
||||
=== Running the httpsession-jdbc Sample Application
|
||||
This section describes how to work with the `httpsession-jdbc` Sample Application.
|
||||
|
||||
=== Running the `httpsession-jdbc` Sample Application
|
||||
|
||||
You can run the sample by obtaining the {download-url}[source code] and invoking the following command:
|
||||
|
||||
====
|
||||
----
|
||||
$ ./gradlew :spring-session-sample-javaconfig-jdbc:tomcatRun
|
||||
----
|
||||
====
|
||||
|
||||
You should now be able to access the application at http://localhost:8080/
|
||||
|
||||
=== Exploring the httpsession-jdbc Sample Application
|
||||
=== Exploring the `httpsession-jdbc` Sample Application
|
||||
|
||||
Try using the application. Fill out the form with the following information:
|
||||
Now you can try using the application. To do so, fill out the form with the following information:
|
||||
|
||||
* **Attribute Name:** _username_
|
||||
* **Attribute Value:** _rob_
|
||||
* *Attribute Name:* _username_
|
||||
* *Attribute Value:* _rob_
|
||||
|
||||
Now click the **Set Attribute** button. You should now see the values displayed in the table.
|
||||
Now click the *Set Attribute* button. You should now see the values displayed in the table.
|
||||
|
||||
=== How does it work?
|
||||
=== How Does It Work?
|
||||
|
||||
We interact with the standard `HttpSession` in the `SessionServlet` shown below:
|
||||
We interact with the standard `HttpSession` in the `SessionServlet` shown in the following listing:
|
||||
|
||||
====
|
||||
.src/main/java/sample/SessionServlet.java
|
||||
[source,java]
|
||||
----
|
||||
include::{samples-dir}javaconfig/jdbc/src/main/java/sample/SessionServlet.java[tags=class]
|
||||
----
|
||||
====
|
||||
|
||||
Instead of using Tomcat's `HttpSession`, we are actually persisting the values in H2 database.
|
||||
Spring Session creates a cookie named SESSION in your browser that contains the id of your session.
|
||||
Go ahead and view the cookies (click for help with https://developers.google.com/web/tools/chrome-devtools/manage-data/cookies[Chrome] or https://developer.mozilla.org/en-US/docs/Tools/Storage_Inspector[Firefox]).
|
||||
Instead of using Tomcat's `HttpSession`, we persist the values in H2 database.
|
||||
Spring Session creates a cookie named `SESSION` in your browser.
|
||||
That cookie contains the ID of your session.
|
||||
You can view the cookies (with https://developers.google.com/web/tools/chrome-devtools/manage-data/cookies[Chrome] or https://developer.mozilla.org/en-US/docs/Tools/Storage_Inspector[Firefox]).
|
||||
|
||||
If you like, you can easily remove the session using H2 web console available at: http://localhost:8080/h2-console/ (use `jdbc:h2:mem:testdb` for JDBC URL)
|
||||
If you like, you can remove the session by using the H2 web console available at: http://localhost:8080/h2-console/ (use `jdbc:h2:mem:testdb` for JDBC URL).
|
||||
|
||||
Now visit the application at http://localhost:8080/ and observe that the attribute we added is no longer displayed.
|
||||
Now you can visit the application at http://localhost:8080/ and see that the attribute we added is no longer displayed.
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
= Spring Session - HttpSession (Quick Start)
|
||||
Rob Winch
|
||||
:toc:
|
||||
:version-snapshot: true
|
||||
|
||||
This guide describes how to use Spring Session to transparently leverage Redis to back a web application's `HttpSession` with Java Configuration.
|
||||
|
||||
NOTE: The completed guide can be found in the <<httpsession-sample, httpsession sample application>>.
|
||||
NOTE: You can find the completed guide in the <<httpsession-sample, httpsession sample application>>.
|
||||
|
||||
== Updating Dependencies
|
||||
Before you use Spring Session, you must ensure to update your dependencies.
|
||||
If you are using Maven, ensure to add the following dependencies:
|
||||
Before you use Spring Session, you must update your dependencies.
|
||||
If you are using Maven, you must add the following dependencies:
|
||||
|
||||
====
|
||||
.pom.xml
|
||||
[source,xml]
|
||||
[subs="verbatim,attributes"]
|
||||
@@ -35,11 +37,13 @@ If you are using Maven, ensure to add the following dependencies:
|
||||
</dependency>
|
||||
</dependencies>
|
||||
----
|
||||
====
|
||||
|
||||
ifeval::["{version-snapshot}" == "true"]
|
||||
Since we are using a SNAPSHOT version, we need to ensure to add the Spring Snapshot Maven Repository.
|
||||
Ensure you have the following in your pom.xml:
|
||||
You must have the following in your pom.xml:
|
||||
|
||||
====
|
||||
.pom.xml
|
||||
[source,xml]
|
||||
----
|
||||
@@ -53,12 +57,14 @@ Ensure you have the following in your pom.xml:
|
||||
</repository>
|
||||
</repositories>
|
||||
----
|
||||
====
|
||||
endif::[]
|
||||
|
||||
ifeval::["{version-milestone}" == "true"]
|
||||
Since We are using a Milestone version, we need to ensure to add the Spring Milestone Maven Repository.
|
||||
Ensure you have the following in your pom.xml:
|
||||
Since we are using a Milestone version, we need to ensure to add the Spring Milestone Maven Repository.
|
||||
You must have the following in your pom.xml:
|
||||
|
||||
====
|
||||
.pom.xml
|
||||
[source,xml]
|
||||
----
|
||||
@@ -67,6 +73,7 @@ Ensure you have the following in your pom.xml:
|
||||
<url>https://repo.spring.io/libs-milestone</url>
|
||||
</repository>
|
||||
----
|
||||
====
|
||||
endif::[]
|
||||
|
||||
// tag::config[]
|
||||
@@ -75,20 +82,22 @@ endif::[]
|
||||
== Spring Java Configuration
|
||||
|
||||
After adding the required dependencies, we can create our Spring configuration.
|
||||
The Spring configuration is responsible for creating a Servlet Filter that replaces the `HttpSession` implementation with an implementation backed by Spring Session.
|
||||
Add the following Spring Configuration:
|
||||
The Spring configuration is responsible for creating a servlet filter that replaces the `HttpSession` implementation with an implementation backed by Spring Session.
|
||||
To do so, add the following Spring Configuration:
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
include::{samples-dir}javaconfig/redis/src/main/java/sample/Config.java[tags=class]
|
||||
----
|
||||
|
||||
<1> 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.
|
||||
<1> The `@EnableRedisHttpSession` annotation creates a Spring Bean with the name of `springSessionRepositoryFilter` that implements `Filter`.
|
||||
The filter 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)
|
||||
For more information on configuring Spring Data Redis, refer to the https://docs.spring.io/spring-data/data-redis/docs/{spring-data-redis-version}/reference/html/[reference documentation].
|
||||
We configure the connection to connect to localhost on the default port (6379).
|
||||
For more information on configuring Spring Data Redis, see the https://docs.spring.io/spring-data/data-redis/docs/{spring-data-redis-version}/reference/html/[reference documentation].
|
||||
====
|
||||
|
||||
== Java Servlet Container Initialization
|
||||
|
||||
@@ -96,22 +105,24 @@ Our <<httpsession-spring-configuration,Spring Configuration>> created a Spring B
|
||||
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.
|
||||
Last we need to ensure that our Servlet Container (i.e. Tomcat) uses our `springSessionRepositoryFilter` for every request.
|
||||
Fortunately, Spring Session provides a utility class named `AbstractHttpSessionApplicationInitializer` both of these steps extremely easy.
|
||||
You can find an example below:
|
||||
Last, we need to ensure that our Servlet Container (that is, Tomcat) uses our `springSessionRepositoryFilter` for every request.
|
||||
Fortunately, Spring Session provides a utility class named `AbstractHttpSessionApplicationInitializer` to make both of these steps easy.
|
||||
The following shows an example:
|
||||
|
||||
====
|
||||
.src/main/java/sample/Initializer.java
|
||||
[source,java]
|
||||
----
|
||||
include::{samples-dir}javaconfig/redis/src/main/java/sample/Initializer.java[tags=class]
|
||||
----
|
||||
|
||||
NOTE: The name of our class (Initializer) does not matter. What is important is that we extend `AbstractHttpSessionApplicationInitializer`.
|
||||
|
||||
NOTE: The name of our class (`Initializer`) does not matter. What is important is that we extend `AbstractHttpSessionApplicationInitializer`.
|
||||
|
||||
<1> The first step is to extend `AbstractHttpSessionApplicationInitializer`.
|
||||
This ensures that the Spring Bean by the name `springSessionRepositoryFilter` is registered with our Servlet Container for every request.
|
||||
<2> `AbstractHttpSessionApplicationInitializer` also provides a mechanism to easily ensure Spring loads our `Config`.
|
||||
|
||||
Doing so ensures that the Spring Bean by the name of `springSessionRepositoryFilter` is registered with our Servlet Container for every request.
|
||||
<2> `AbstractHttpSessionApplicationInitializer` also provides a mechanism to ensure Spring loads our `Config`.
|
||||
====
|
||||
// end::config[]
|
||||
|
||||
[[httpsession-sample]]
|
||||
@@ -119,54 +130,66 @@ This ensures that the Spring Bean by the name `springSessionRepositoryFilter` is
|
||||
|
||||
|
||||
|
||||
=== Running the httpsession Sample Application
|
||||
=== Running the `httpsession` Sample Application
|
||||
|
||||
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 https://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
|
||||
Alternatively, you can update the `RedisConnectionFactory` to point to a Redis server.
|
||||
Another option is to use https://www.docker.com/[Docker] to run Redis on localhost. See https://hub.docker.com/_/redis/[Docker Redis repository] for detailed instructions.
|
||||
====
|
||||
|
||||
----
|
||||
$ ./gradlew :spring-session-sample-javaconfig-redis:tomcatRun
|
||||
----
|
||||
====
|
||||
|
||||
NOTE: For the sample to work, you must https://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
|
||||
Alternatively, you can update the `RedisConnectionFactory` to point to a Redis server.
|
||||
Another option is to use https://www.docker.com/[Docker] to run Redis on localhost.
|
||||
See https://hub.docker.com/_/redis/[Docker Redis repository] for detailed instructions.
|
||||
|
||||
You should now be able to access the application at http://localhost:8080/
|
||||
|
||||
=== Exploring the httpsession Sample Application
|
||||
=== Exploring the `httpsession` Sample Application
|
||||
|
||||
Try using the application. Fill out the form with the following information:
|
||||
Now you can try to use the application. To do so, fill out the form with the following information:
|
||||
|
||||
* **Attribute Name:** _username_
|
||||
* **Attribute Value:** _rob_
|
||||
* *Attribute Name:* _username_
|
||||
* *Attribute Value:* _rob_
|
||||
|
||||
Now click the **Set Attribute** button. You should now see the values displayed in the table.
|
||||
Now click the *Set Attribute* button. You should now see the values displayed in the table.
|
||||
|
||||
=== How does it work?
|
||||
=== How Does It Work?
|
||||
|
||||
We interact with the standard `HttpSession` in the `SessionServlet` shown below:
|
||||
We interact with the standard `HttpSession` in the `SessionServlet` shown in the following listing:
|
||||
|
||||
====
|
||||
.src/main/java/sample/SessionServlet.java
|
||||
[source,java]
|
||||
----
|
||||
include::{samples-dir}javaconfig/redis/src/main/java/sample/SessionServlet.java[tags=class]
|
||||
----
|
||||
====
|
||||
|
||||
Instead of using Tomcat's `HttpSession`, we are actually persisting the values in Redis.
|
||||
Spring Session creates a cookie named SESSION in your browser that contains the id of your session.
|
||||
Go ahead and view the cookies (click for help with https://developers.google.com/web/tools/chrome-devtools/manage-data/cookies[Chrome] or https://developer.mozilla.org/en-US/docs/Tools/Storage_Inspector[Firefox]).
|
||||
Instead of using Tomcat's `HttpSession`, we persist the values in Redis.
|
||||
Spring Session creates a cookie named `SESSION` in your browser.
|
||||
That cookie contains the ID of your session.
|
||||
You can view the cookies (with https://developers.google.com/web/tools/chrome-devtools/manage-data/cookies[Chrome] or https://developer.mozilla.org/en-US/docs/Tools/Storage_Inspector[Firefox]).
|
||||
|
||||
If you like, you can easily remove the session using redis-cli. For example, on a Linux based system you can type:
|
||||
You can remove the session by using redis-cli.
|
||||
For example, on a Linux based system you can type the following:
|
||||
|
||||
====
|
||||
----
|
||||
$ redis-cli keys '*' | xargs redis-cli del
|
||||
----
|
||||
====
|
||||
|
||||
TIP: The Redis documentation has instructions for https://redis.io/topics/quickstart[installing redis-cli].
|
||||
|
||||
Alternatively, you can also delete the explicit key. Enter the following into your terminal ensuring to replace `7e8383a4-082c-4ffe-a4bc-c40fd3363c5e` with the value of your SESSION cookie:
|
||||
Alternatively, you can also delete the explicit key. Enter the following into your terminal, being sure to replace `7e8383a4-082c-4ffe-a4bc-c40fd3363c5e` with the value of your SESSION cookie:
|
||||
|
||||
====
|
||||
----
|
||||
$ redis-cli del spring:session:sessions:7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
|
||||
----
|
||||
====
|
||||
|
||||
Now visit the application at http://localhost:8080/ and observe that the attribute we added is no longer displayed.
|
||||
Now you can visit the application at http://localhost:8080/ and see that the attribute we added is no longer displayed.
|
||||
|
||||
@@ -2,14 +2,16 @@
|
||||
Rob Winch
|
||||
:toc:
|
||||
|
||||
This guide describes how to use Spring Session to transparently leverage Redis to back a web application's `HttpSession` when using REST endpoints.
|
||||
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: The completed guide can be found in the <<rest-sample, rest sample application>>.
|
||||
NOTE: You can find the completed guide in the <<rest-sample, rest sample application>>.
|
||||
|
||||
== Updating Dependencies
|
||||
Before you use Spring Session, you must ensure to update your dependencies.
|
||||
If you are using Maven, ensure to add the following dependencies:
|
||||
|
||||
Before you use Spring Session, you must update your dependencies.
|
||||
If you use Maven, you must add the following dependencies:
|
||||
|
||||
====
|
||||
.pom.xml
|
||||
[source,xml]
|
||||
[subs="verbatim,attributes"]
|
||||
@@ -35,11 +37,13 @@ If you are using Maven, ensure to add the following dependencies:
|
||||
</dependency>
|
||||
</dependencies>
|
||||
----
|
||||
====
|
||||
|
||||
ifeval::["{version-snapshot}" == "true"]
|
||||
Since We are using a SNAPSHOT version, we need to ensure to add the Spring Snapshot Maven Repository.
|
||||
Ensure you have the following in your pom.xml:
|
||||
Since we are using a SNAPSHOT version, we need to ensure to add the Spring Snapshot Maven Repository.
|
||||
You must have the following in your pom.xml:
|
||||
|
||||
====
|
||||
.pom.xml
|
||||
[source,xml]
|
||||
----
|
||||
@@ -53,12 +57,14 @@ Ensure you have the following in your pom.xml:
|
||||
</repository>
|
||||
</repositories>
|
||||
----
|
||||
====
|
||||
endif::[]
|
||||
|
||||
ifeval::["{version-milestone}" == "true"]
|
||||
Since We are using a Milestone version, we need to ensure to add the Spring Milestone Maven Repository.
|
||||
Ensure you have the following in your pom.xml:
|
||||
Since we are using a Milestone version, we need to add the Spring Milestone Maven Repository.
|
||||
You msut have the following in your pom.xml:
|
||||
|
||||
====
|
||||
.pom.xml
|
||||
[source,xml]
|
||||
----
|
||||
@@ -67,6 +73,7 @@ Ensure you have the following in your pom.xml:
|
||||
<url>https://repo.spring.io/libs-milestone</url>
|
||||
</repository>
|
||||
----
|
||||
====
|
||||
endif::[]
|
||||
|
||||
// tag::config[]
|
||||
@@ -75,83 +82,103 @@ endif::[]
|
||||
== Spring Configuration
|
||||
|
||||
After adding the required dependencies, we can create our Spring configuration.
|
||||
The Spring configuration is responsible for creating a Servlet Filter that replaces the `HttpSession` implementation with an implementation backed by Spring Session.
|
||||
Add the following Spring Configuration:
|
||||
The Spring configuration is responsible for creating a servlet filter that replaces the `HttpSession` implementation with an implementation backed by Spring Session.
|
||||
To do so, add the following Spring Configuration:
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
include::{samples-dir}javaconfig/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`.
|
||||
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.
|
||||
<1> The `@EnableRedisHttpSession` annotation creates a Spring bean named `springSessionRepositoryFilter` that implements `Filter`.
|
||||
The filter 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)
|
||||
For more information on configuring Spring Data Redis, refer to the https://docs.spring.io/spring-data/data-redis/docs/{spring-data-redis-version}/reference/html/[reference documentation].
|
||||
We configure the connection to connect to localhost on the default port (6379).
|
||||
For more information on configuring Spring Data Redis, see the https://docs.spring.io/spring-data/data-redis/docs/{spring-data-redis-version}/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.
|
||||
====
|
||||
|
||||
== Servlet Container Initialization
|
||||
|
||||
Our <<rest-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. We provide the configuration in our Spring `MvcInitializer` as shown below:
|
||||
In order for our `Filter` to do its magic, Spring needs to load our `Config` class.
|
||||
We provide the configuration in our Spring `MvcInitializer`, as the following example shows:
|
||||
|
||||
====
|
||||
.src/main/java/sample/mvc/MvcInitializer.java
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::{samples-dir}javaconfig/rest/src/main/java/sample/mvc/MvcInitializer.java[tags=config]
|
||||
----
|
||||
====
|
||||
|
||||
Last we need to ensure that our Servlet Container (i.e. Tomcat) uses our `springSessionRepositoryFilter` for every request.
|
||||
Fortunately, Spring Session provides a utility class named `AbstractHttpSessionApplicationInitializer` that makes this extremely easy. Simply extend the class with the default constructor as shown below:
|
||||
Last, we need to ensure that our Servlet Container (that is, Tomcat) uses our `springSessionRepositoryFilter` for every request.
|
||||
Fortunately, Spring Session provides a utility class named `AbstractHttpSessionApplicationInitializer` that makes doing so easy. To do so, extend the class with the default constructor, as the following example shows:
|
||||
|
||||
====
|
||||
.src/main/java/sample/Initializer.java
|
||||
[source,java]
|
||||
----
|
||||
include::{samples-dir}javaconfig/rest/src/main/java/sample/Initializer.java[tags=class]
|
||||
----
|
||||
====
|
||||
|
||||
NOTE: The name of our class (Initializer) does not matter. What is important is that we extend `AbstractHttpSessionApplicationInitializer`.
|
||||
NOTE: The name of our class (`Initializer`) does not matter. What is important is that we extend `AbstractHttpSessionApplicationInitializer`.
|
||||
|
||||
// end::config[]
|
||||
|
||||
[[rest-sample]]
|
||||
== rest Sample Application
|
||||
== `rest` Sample Application
|
||||
|
||||
=== Running the rest Sample Application
|
||||
This section describes how to use the `rest` sample application.
|
||||
|
||||
=== Running the `rest` Sample Application
|
||||
|
||||
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 https://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
|
||||
NOTE: For the sample to work, you must https://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
|
||||
Alternatively, you can update the `RedisConnectionFactory` to point to a Redis server.
|
||||
Another option is to use https://www.docker.com/[Docker] to run Redis on localhost. See https://hub.docker.com/_/redis/[Docker Redis repository] for detailed instructions.
|
||||
====
|
||||
Another option is to use https://www.docker.com/[Docker] to run Redis on localhost.
|
||||
See https://hub.docker.com/_/redis/[Docker Redis repository] for detailed instructions.
|
||||
|
||||
====
|
||||
----
|
||||
$ ./gradlew :spring-session-sample-javaconfig-rest:tomcatRun
|
||||
----
|
||||
====
|
||||
|
||||
You should now be able to access the application at http://localhost:8080/
|
||||
|
||||
=== Exploring the rest Sample Application
|
||||
=== Exploring the `rest` Sample Application
|
||||
|
||||
Try using the application. Use your favorite REST client to request http://localhost:8080/
|
||||
You can now try to use the application. To do so, use your favorite REST client to request http://localhost:8080/
|
||||
|
||||
====
|
||||
----
|
||||
$ curl -v http://localhost:8080/
|
||||
----
|
||||
====
|
||||
|
||||
Observe that we are prompted for basic authentication. Provide the following information for the username and password:
|
||||
Note that you are prompted for basic authentication. Provide the following information for the username and password:
|
||||
|
||||
* **Username** *user*
|
||||
* **Password** *password*
|
||||
* *Username* _user-
|
||||
* *Password* _password_
|
||||
|
||||
Then run the following command:
|
||||
|
||||
====
|
||||
----
|
||||
$ curl -v http://localhost:8080/ -u user:password
|
||||
----
|
||||
====
|
||||
|
||||
In the output you will notice the following:
|
||||
In the output, you should notice the following:
|
||||
|
||||
====
|
||||
----
|
||||
HTTP/1.1 200 OK
|
||||
...
|
||||
@@ -159,44 +186,62 @@ X-Auth-Token: 0dc1f6e1-c7f1-41ac-8ce2-32b6b3e57aa3
|
||||
|
||||
{"username":"user"}
|
||||
----
|
||||
====
|
||||
|
||||
Specifically, we notice the following things about our response:
|
||||
Specifically, you should notice the following things about our response:
|
||||
|
||||
* The HTTP Status is now a 200
|
||||
* We have a header with the name of *X-Auth-Token* which contains a new session id
|
||||
* The current username is displayed
|
||||
* The HTTP Status is now a 200.
|
||||
* We have a header a the name of `X-Auth-Token` and that contains a new session ID.
|
||||
* The current username is displayed.
|
||||
|
||||
We can now use the *X-Auth-Token* to make another request without providing the username and password again. For example, the following outputs the username just as before:
|
||||
We can now use the `X-Auth-Token` to make another request without providing the username and password again. For example, the following command outputs the username, as before:
|
||||
|
||||
====
|
||||
----
|
||||
$ curl -v http://localhost:8080/ -H "X-Auth-Token: 0dc1f6e1-c7f1-41ac-8ce2-32b6b3e57aa3"
|
||||
----
|
||||
====
|
||||
|
||||
The only difference is that the session id is not provided in the response headers because we are reusing an existing session.
|
||||
The only difference is that the session ID is not provided in the response headers because we are reusing an existing session.
|
||||
|
||||
If we invalidate the session, then the X-Auth-Token is displayed in the response with an empty value. For example, the following will invalidate our session:
|
||||
If we invalidate the session, the `X-Auth-Token` is displayed in the response with an empty value. For example, the following command invalidates our session:
|
||||
|
||||
====
|
||||
----
|
||||
$ curl -v http://localhost:8080/logout -H "X-Auth-Token: 0dc1f6e1-c7f1-41ac-8ce2-32b6b3e57aa3"
|
||||
----
|
||||
====
|
||||
|
||||
You will see in the output that the X-Auth-Token provides an empty String indicating that the previous session was invalidated.
|
||||
You can see in the output that the `X-Auth-Token` provides an empty `String` indicating that the previous session was invalidated:
|
||||
|
||||
====
|
||||
----
|
||||
HTTP/1.1 204 No Content
|
||||
...
|
||||
X-Auth-Token:
|
||||
----
|
||||
====
|
||||
|
||||
=== How does it work?
|
||||
=== How Does It Work?
|
||||
|
||||
Spring Security interacts with the standard `HttpSession` in `SecurityContextPersistenceFilter`.
|
||||
|
||||
Instead of using Tomcat's `HttpSession`, Spring Security is now persisting the values in Redis.
|
||||
Spring Session creates a header named X-Auth-Token in your browser that contains the id of your session.
|
||||
Spring Session creates a header named `X-Auth-Token` in your browser.
|
||||
That header contains the ID of your session.
|
||||
|
||||
If you like, you can easily see that the session is created in Redis. First create a session using the following:
|
||||
If you like, you can easily see that the session is created in Redis.
|
||||
To do so, create a session by using the following command:
|
||||
|
||||
====
|
||||
----
|
||||
$ curl -v http://localhost:8080/ -u user:password
|
||||
----
|
||||
====
|
||||
|
||||
In the output you will notice the following:
|
||||
In the output, you should notice the following:
|
||||
|
||||
===
|
||||
----
|
||||
HTTP/1.1 200 OK
|
||||
...
|
||||
@@ -204,17 +249,32 @@ X-Auth-Token: 7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
|
||||
|
||||
{"username":"user"}
|
||||
----
|
||||
====
|
||||
|
||||
Now remove the session using redis-cli. For example, on a Linux based system you can type:
|
||||
Now you can remove the session by using redis-cli.
|
||||
For example, on a Linux based system, you can type:
|
||||
|
||||
====
|
||||
----
|
||||
$ redis-cli keys '*' | xargs redis-cli del
|
||||
----
|
||||
====
|
||||
|
||||
TIP: The Redis documentation has instructions for https://redis.io/topics/quickstart[installing redis-cli].
|
||||
|
||||
Alternatively, you can also delete the explicit key. Enter the following into your terminal ensuring to replace `7e8383a4-082c-4ffe-a4bc-c40fd3363c5e` with the value of your SESSION cookie:
|
||||
Alternatively, you can also delete the explicit key.
|
||||
To do so, enter the following into your terminal, being sure to replace `7e8383a4-082c-4ffe-a4bc-c40fd3363c5e` with the value of your `SESSION` cookie:
|
||||
|
||||
====
|
||||
----
|
||||
$ redis-cli del spring:session:sessions:7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
|
||||
----
|
||||
====
|
||||
|
||||
We can now use the *X-Auth-Token* to make another request with the session we deleted and observe we are prompted for a authentication. For example, the following returns an HTTP 401:
|
||||
We can now use the `X-Auth-Token` to make another request with the session we deleted and observe we that are prompted for authentication. For example, the following returns an HTTP 401:
|
||||
|
||||
====
|
||||
----
|
||||
$ curl -v http://localhost:8080/ -H "X-Auth-Token: 0dc1f6e1-c7f1-41ac-8ce2-32b6b3e57aa3"
|
||||
----
|
||||
====
|
||||
|
||||
@@ -5,12 +5,13 @@ Rob Winch
|
||||
This guide describes how to use Spring Session along with Spring Security.
|
||||
It assumes you have already applied Spring Security to your application.
|
||||
|
||||
NOTE: The completed guide can be found in the <<security-sample, security sample application>>.
|
||||
NOTE: You can find the completed guide in the <<security-sample, security sample application>>.
|
||||
|
||||
== Updating Dependencies
|
||||
Before you use Spring Session, you must ensure to update your dependencies.
|
||||
If you are using Maven, ensure to add the following dependencies:
|
||||
Before you use Spring Session, you must update your dependencies.
|
||||
If you use Maven, you must add the following dependencies:
|
||||
|
||||
====
|
||||
.pom.xml
|
||||
[source,xml]
|
||||
[subs="verbatim,attributes"]
|
||||
@@ -36,11 +37,13 @@ If you are using Maven, ensure to add the following dependencies:
|
||||
</dependency>
|
||||
</dependencies>
|
||||
----
|
||||
====
|
||||
|
||||
ifeval::["{version-snapshot}" == "true"]
|
||||
Since We are using a SNAPSHOT version, we need to ensure to add the Spring Snapshot Maven Repository.
|
||||
Ensure you have the following in your pom.xml:
|
||||
Since we are using a SNAPSHOT version, we need to add the Spring Snapshot Maven Repository.
|
||||
You must have the following in your pom.xml:
|
||||
|
||||
====
|
||||
.pom.xml
|
||||
[source,xml]
|
||||
----
|
||||
@@ -54,12 +57,14 @@ Ensure you have the following in your pom.xml:
|
||||
</repository>
|
||||
</repositories>
|
||||
----
|
||||
====
|
||||
endif::[]
|
||||
|
||||
ifeval::["{version-milestone}" == "true"]
|
||||
Since We are using a Milestone version, we need to ensure to add the Spring Milestone Maven Repository.
|
||||
Ensure you have the following in your pom.xml:
|
||||
Since we are using a Milestone version, we need to add the Spring Milestone Maven Repository.
|
||||
You must have the following in your pom.xml:
|
||||
|
||||
====
|
||||
.pom.xml
|
||||
[source,xml]
|
||||
----
|
||||
@@ -68,107 +73,121 @@ Ensure you have the following in your pom.xml:
|
||||
<url>https://repo.spring.io/libs-milestone</url>
|
||||
</repository>
|
||||
----
|
||||
====
|
||||
endif::[]
|
||||
|
||||
[[security-spring-configuration]]
|
||||
== Spring Configuration
|
||||
|
||||
After adding the required dependencies, we can create our Spring configuration.
|
||||
The Spring configuration is responsible for creating a Servlet Filter that replaces the `HttpSession` implementation with an implementation backed by Spring Session.
|
||||
Add the following Spring Configuration:
|
||||
The Spring configuration is responsible for creating a servlet filter that replaces the `HttpSession` implementation with an implementation backed by Spring Session.
|
||||
To do so, add the following Spring Configuration:
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
include::{samples-dir}javaconfig/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.
|
||||
The filter is what is in charge of replacing the `HttpSession` implementation to be backed by Spring Session.
|
||||
<1> The `@EnableRedisHttpSession` annotation creates a Spring bean with the name of `springSessionRepositoryFilter` that implements `Filter`.
|
||||
The filter 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)
|
||||
For more information on configuring Spring Data Redis, refer to the https://docs.spring.io/spring-data/data-redis/docs/{spring-data-redis-version}/reference/html/[reference documentation].
|
||||
For more information on configuring Spring Data Redis, see the https://docs.spring.io/spring-data/data-redis/docs/{spring-data-redis-version}/reference/html/[reference documentation].
|
||||
====
|
||||
|
||||
== Servlet Container Initialization
|
||||
|
||||
Our <<security-spring-configuration,Spring Configuration>> created a Spring Bean named `springSessionRepositoryFilter` that implements `Filter`.
|
||||
Our <<security-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.
|
||||
Since our application is already loading Spring configuration using our `SecurityInitializer` class, we can simply add our Config class to it.
|
||||
Since our application is already loading Spring configuration by using our `SecurityInitializer` class, we can add our configuration class to it.
|
||||
The following example shows how to do so:
|
||||
|
||||
====
|
||||
.src/main/java/sample/SecurityInitializer.java
|
||||
[source,java]
|
||||
----
|
||||
include::{samples-dir}javaconfig/security/src/main/java/sample/SecurityInitializer.java[tags=class]
|
||||
----
|
||||
====
|
||||
|
||||
Last we need to ensure that our Servlet Container (i.e. Tomcat) uses our `springSessionRepositoryFilter` for every request.
|
||||
Last, we need to ensure that our Servlet Container (that is, Tomcat) uses our `springSessionRepositoryFilter` for every request.
|
||||
It is extremely important that Spring Session's `springSessionRepositoryFilter` is invoked before Spring Security's `springSecurityFilterChain`.
|
||||
This ensures that the `HttpSession` that Spring Security uses is backed by Spring Session.
|
||||
Fortunately, Spring Session provides a utility class named `AbstractHttpSessionApplicationInitializer` that makes this extremely easy.
|
||||
You can find an example below:
|
||||
Fortunately, Spring Session provides a utility class named `AbstractHttpSessionApplicationInitializer` that makes doing so easy.
|
||||
The following example shows how to do so:
|
||||
|
||||
====
|
||||
.src/main/java/sample/Initializer.java
|
||||
[source,java]
|
||||
----
|
||||
include::{samples-dir}javaconfig/security/src/main/java/sample/Initializer.java[tags=class]
|
||||
----
|
||||
====
|
||||
|
||||
NOTE: The name of our class (Initializer) does not matter. What is important is that we extend `AbstractHttpSessionApplicationInitializer`.
|
||||
|
||||
By extending `AbstractHttpSessionApplicationInitializer` we ensure that the Spring Bean by the name `springSessionRepositoryFilter` is registered with our Servlet Container for every request before Spring Security's `springSecurityFilterChain` .
|
||||
By extending `AbstractHttpSessionApplicationInitializer`, we ensure that the Spring bean named `springSessionRepositoryFilter` is registered with our Servlet Container for every request before Spring Security's `springSecurityFilterChain` .
|
||||
|
||||
[[security-sample]]
|
||||
== security Sample Application
|
||||
== `security` Sample Application
|
||||
|
||||
This section describes how to work with the `security` sample application.
|
||||
|
||||
|
||||
=== Running the security Sample Application
|
||||
=== Running the `security` Sample Application
|
||||
|
||||
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 https://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
|
||||
Alternatively, you can update the `RedisConnectionFactory` to point to a Redis server.
|
||||
Another option is to use https://www.docker.com/[Docker] to run Redis on localhost. See https://hub.docker.com/_/redis/[Docker Redis repository] for detailed instructions.
|
||||
====
|
||||
|
||||
----
|
||||
$ ./gradlew :spring-session-sample-javaconfig-security:tomcatRun
|
||||
----
|
||||
====
|
||||
|
||||
NOTE: For the sample to work, you must https://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
|
||||
Alternatively, you can update the `RedisConnectionFactory` to point to a Redis server.
|
||||
Another option is to use https://www.docker.com/[Docker] to run Redis on localhost.
|
||||
See https://hub.docker.com/_/redis/[Docker Redis repository] for detailed instructions.
|
||||
|
||||
You should now be able to access the application at http://localhost:8080/
|
||||
|
||||
=== Exploring the security Sample Application
|
||||
=== Exploring the `security` Sample Application
|
||||
|
||||
Try using the application. Enter the following to log in:
|
||||
Now you can use the application. Enter the following to log in:
|
||||
|
||||
* **Username** _user_
|
||||
* **Password** _password_
|
||||
* *Username* _user_
|
||||
* *Password* _password_
|
||||
|
||||
Now click the **Login** button.
|
||||
Now click the *Login* button.
|
||||
You should now see a message indicating your are logged in with the user entered previously.
|
||||
The user's information is stored in Redis rather than Tomcat's `HttpSession` implementation.
|
||||
|
||||
=== How does it work?
|
||||
=== How Does It Work?
|
||||
|
||||
Instead of using Tomcat's `HttpSession`, we are actually persisting the values in Redis.
|
||||
Instead of using Tomcat's `HttpSession`, we persist the values in Redis.
|
||||
Spring Session replaces the `HttpSession` with an implementation that is backed by Redis.
|
||||
When Spring Security's `SecurityContextPersistenceFilter` saves the `SecurityContext` to the `HttpSession` it is then persisted into Redis.
|
||||
When Spring Security's `SecurityContextPersistenceFilter` saves the `SecurityContext` to the `HttpSession`, it is then persisted into Redis.
|
||||
|
||||
When a new `HttpSession` is created, Spring Session creates a cookie named SESSION in your browser that contains the id of your session.
|
||||
Go ahead and view the cookies (click for help with https://developers.google.com/web/tools/chrome-devtools/manage-data/cookies[Chrome] or https://developer.mozilla.org/en-US/docs/Tools/Storage_Inspector[Firefox]).
|
||||
When a new `HttpSession` is created, Spring Session creates a cookie named `SESSION` in your browser.
|
||||
That cookie contains the ID of your session.
|
||||
You can view the cookies (with https://developers.google.com/web/tools/chrome-devtools/manage-data/cookies[Chrome] or https://developer.mozilla.org/en-US/docs/Tools/Storage_Inspector[Firefox]).
|
||||
|
||||
If you like, you can easily remove the session using redis-cli. For example, on a Linux based system you can type:
|
||||
You can remove the session using redis-cli. For example, on a Linux-based system you can type the following command:
|
||||
|
||||
====
|
||||
----
|
||||
$ redis-cli keys '*' | xargs redis-cli del
|
||||
----
|
||||
====
|
||||
|
||||
TIP: The Redis documentation has instructions for https://redis.io/topics/quickstart[installing redis-cli].
|
||||
|
||||
Alternatively, you can also delete the explicit key. Enter the following into your terminal ensuring to replace `7e8383a4-082c-4ffe-a4bc-c40fd3363c5e` with the value of your SESSION cookie:
|
||||
Alternatively, you can also delete the explicit key.
|
||||
Enter the following command into your terminal, being sure to replace `7e8383a4-082c-4ffe-a4bc-c40fd3363c5e` with the value of your `SESSION` cookie:
|
||||
|
||||
$ redis-cli del spring:session:sessions:7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
|
||||
|
||||
Now visit the application at http://localhost:8080/ and observe that we are no longer authenticated.
|
||||
Now you can visit the application at http://localhost:8080/ and see that we are no longer authenticated.
|
||||
|
||||
@@ -4,12 +4,14 @@ Rob Winch, Vedran Pavić
|
||||
|
||||
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: The completed guide can be found in the <<httpsession-jdbc-xml-sample, httpsession-jdbc-xml sample application>>.
|
||||
NOTE: You can find the completed guide in the <<httpsession-jdbc-xml-sample, httpsession-jdbc-xml sample application>>.
|
||||
|
||||
== Updating Dependencies
|
||||
Before you use Spring Session, you must ensure to update your dependencies.
|
||||
If you are using Maven, ensure to add the following dependencies:
|
||||
|
||||
Before you use Spring Session, you must update your dependencies.
|
||||
If you are using Maven, you must add the following dependencies:
|
||||
|
||||
====
|
||||
.pom.xml
|
||||
[source,xml]
|
||||
[subs="verbatim,attributes"]
|
||||
@@ -30,11 +32,13 @@ If you are using Maven, ensure to add the following dependencies:
|
||||
</dependency>
|
||||
</dependencies>
|
||||
----
|
||||
====
|
||||
|
||||
ifeval::["{version-snapshot}" == "true"]
|
||||
Since we are using a SNAPSHOT version, we need to ensure to add the Spring Snapshot Maven Repository.
|
||||
Ensure you have the following in your pom.xml:
|
||||
Since we are using a SNAPSHOT version, we need to add the Spring Snapshot Maven Repository.
|
||||
You must have the following in your pom.xml:
|
||||
|
||||
====
|
||||
.pom.xml
|
||||
[source,xml]
|
||||
----
|
||||
@@ -48,12 +52,14 @@ Ensure you have the following in your pom.xml:
|
||||
</repository>
|
||||
</repositories>
|
||||
----
|
||||
====
|
||||
endif::[]
|
||||
|
||||
ifeval::["{version-milestone}" == "true"]
|
||||
Since We are using a Milestone version, we need to ensure to add the Spring Milestone Maven Repository.
|
||||
Ensure you have the following in your pom.xml:
|
||||
Since we are using a Milestone version, we need to add the Spring Milestone Maven Repository.
|
||||
You must have the following in your pom.xml:
|
||||
|
||||
====
|
||||
.pom.xml
|
||||
[source,xml]
|
||||
----
|
||||
@@ -63,6 +69,7 @@ Ensure you have the following in your pom.xml:
|
||||
</repository>
|
||||
----
|
||||
endif::[]
|
||||
====
|
||||
|
||||
// tag::config[]
|
||||
|
||||
@@ -70,9 +77,10 @@ endif::[]
|
||||
== Spring XML Configuration
|
||||
|
||||
After adding the required dependencies, we can create our Spring configuration.
|
||||
The Spring configuration is responsible for creating a Servlet Filter that replaces the `HttpSession` implementation with an implementation backed by Spring Session.
|
||||
Add the following Spring Configuration:
|
||||
The Spring configuration is responsible for creating a servlet filter that replaces the `HttpSession` implementation with an implementation backed by Spring Session.
|
||||
The following listing shows how to add the following Spring Configuration:
|
||||
|
||||
====
|
||||
.src/main/webapp/WEB-INF/spring/session.xml
|
||||
[source,xml,indent=0]
|
||||
----
|
||||
@@ -80,83 +88,94 @@ include::{samples-dir}xml/jdbc/src/main/webapp/WEB-INF/spring/session.xml[tags=b
|
||||
----
|
||||
|
||||
<1> We use the combination of `<context:annotation-config/>` and `JdbcHttpSessionConfiguration` 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 a relational database.
|
||||
<2> We create a `dataSource` that connects Spring Session to an embedded instance of H2 database.
|
||||
We configure the H2 database to create database tables using the SQL script which is included in Spring Session.
|
||||
This creates a Spring bean with the name of `springSessionRepositoryFilter`.
|
||||
That bean implements `Filter`.
|
||||
The filter is in charge of replacing the `HttpSession` implementation to be backed by Spring Session.
|
||||
In this instance, Spring Session is backed by a relational database.
|
||||
<2> We create a `dataSource` that connects Spring Session to an embedded instance of an H2 database.
|
||||
We configure the H2 database to create database tables by using the SQL script that is included in Spring Session.
|
||||
<3> We create a `transactionManager` that manages transactions for previously configured `dataSource`.
|
||||
====
|
||||
|
||||
For additional information on how to configure data access related concerns, please refer to the https://docs.spring.io/spring/docs/{spring-framework-version}/spring-framework-reference/data-access.html[Spring Framework Reference Documentation].
|
||||
For additional information on how to configure data access-related concerns, see the https://docs.spring.io/spring/docs/{spring-framework-version}/spring-framework-reference/data-access.html[Spring Framework Reference Documentation].
|
||||
|
||||
== XML Servlet Container Initialization
|
||||
|
||||
Our <<httpsession-xml-spring-configuration,Spring Configuration>> created a Spring Bean named `springSessionRepositoryFilter` that implements `Filter`.
|
||||
Our <<httpsession-xml-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, we need to instruct Spring to load our `session.xml` configuration.
|
||||
We do this with the following configuration:
|
||||
|
||||
We do so with the following configuration:
|
||||
|
||||
====
|
||||
.src/main/webapp/WEB-INF/web.xml
|
||||
[source,xml,indent=0]
|
||||
----
|
||||
include::{samples-dir}xml/jdbc/src/main/webapp/WEB-INF/web.xml[tags=context-param]
|
||||
include::{samples-dir}xml/jdbc/src/main/webapp/WEB-INF/web.xml[tags=listeners]
|
||||
----
|
||||
====
|
||||
|
||||
The https://docs.spring.io/spring/docs/{spring-framework-version}/spring-framework-reference/core.html#context-create[ContextLoaderListener] reads the contextConfigLocation and picks up our session.xml configuration.
|
||||
The https://docs.spring.io/spring/docs/{spring-framework-version}/spring-framework-reference/core.html#context-create[`ContextLoaderListener`] reads the `contextConfigLocation` and picks up our session.xml configuration.
|
||||
|
||||
Last we need to ensure that our Servlet Container (i.e. Tomcat) uses our `springSessionRepositoryFilter` for every request.
|
||||
Last, we need to ensure that our Servlet Container (that is, Tomcat) uses our `springSessionRepositoryFilter` for every request.
|
||||
The following snippet performs this last step for us:
|
||||
|
||||
====
|
||||
.src/main/webapp/WEB-INF/web.xml
|
||||
[source,xml,indent=0]
|
||||
----
|
||||
include::{samples-dir}xml/jdbc/src/main/webapp/WEB-INF/web.xml[tags=springSessionRepositoryFilter]
|
||||
----
|
||||
====
|
||||
|
||||
The https://docs.spring.io/spring-framework/docs/{spring-framework-version}/javadoc-api/org/springframework/web/filter/DelegatingFilterProxy.html[DelegatingFilterProxy] will look up a Bean by the name of `springSessionRepositoryFilter` and cast it to a `Filter`.
|
||||
For every request that `DelegatingFilterProxy` is invoked, the `springSessionRepositoryFilter` will be invoked.
|
||||
The https://docs.spring.io/spring-framework/docs/{spring-framework-version}/javadoc-api/org/springframework/web/filter/DelegatingFilterProxy.html[`DelegatingFilterProxy`] looks up a bean named `springSessionRepositoryFilter` and casts it to a `Filter`.
|
||||
For every request on which `DelegatingFilterProxy` is invoked, the `springSessionRepositoryFilter` is invoked.
|
||||
|
||||
// end::config[]
|
||||
|
||||
[[httpsession-jdbc-xml-sample]]
|
||||
== httpsession-jdbc-xml Sample Application
|
||||
== `httpsession-jdbc-xml` Sample Application
|
||||
|
||||
=== Running the httpsession-jdbc-xml Sample Application
|
||||
This section describes how to work with the `httpsession-jdbc-xml` Sample Application.
|
||||
|
||||
=== Running the `httpsession-jdbc-xml` Sample Application
|
||||
|
||||
You can run the sample by obtaining the {download-url}[source code] and invoking the following command:
|
||||
|
||||
====
|
||||
----
|
||||
$ ./gradlew :spring-session-sample-xml-jdbc:tomcatRun
|
||||
----
|
||||
====
|
||||
|
||||
You should now be able to access the application at http://localhost:8080/
|
||||
|
||||
=== Exploring the httpsession-jdbc-xml Sample Application
|
||||
=== Exploring the `httpsession-jdbc-xml` Sample Application
|
||||
|
||||
Try using the application. Fill out the form with the following information:
|
||||
Now you can try using the application. To do so, fill out the form with the following information:
|
||||
|
||||
* **Attribute Name:** _username_
|
||||
* **Attribute Value:** _rob_
|
||||
* *Attribute Name:* _username_
|
||||
* *Attribute Value:* _rob_
|
||||
|
||||
Now click the **Set Attribute** button. You should now see the values displayed in the table.
|
||||
Now click the *Set Attribute* button. You should now see the values displayed in the table.
|
||||
|
||||
=== How does it work?
|
||||
=== How Does It Work?
|
||||
|
||||
We interact with the standard `HttpSession` in the `SessionServlet` shown below:
|
||||
We interact with the standard `HttpSession` in the following `SessionServlet`:
|
||||
|
||||
====
|
||||
.src/main/java/sample/SessionServlet.java
|
||||
[source,java]
|
||||
----
|
||||
include::{samples-dir}xml/jdbc/src/main/java/sample/SessionServlet.java[tags=class]
|
||||
----
|
||||
====
|
||||
|
||||
Instead of using Tomcat's `HttpSession`, we are actually persisting the values in H2 database.
|
||||
Spring Session creates a cookie named SESSION in your browser that contains the id of your session.
|
||||
Go ahead and view the cookies (click for help with https://developers.google.com/web/tools/chrome-devtools/manage-data/cookies[Chrome] or https://developer.mozilla.org/en-US/docs/Tools/Storage_Inspector[Firefox]).
|
||||
Instead of using Tomcat's `HttpSession`, we persist the values in the H2 database.
|
||||
Spring Session creates a cookie named `SESSION` in your browser. That cookie contains the ID of your session.
|
||||
You can view the cookies (with https://developers.google.com/web/tools/chrome-devtools/manage-data/cookies[Chrome] or https://developer.mozilla.org/en-US/docs/Tools/Storage_Inspector[Firefox]).
|
||||
|
||||
If you like, you can easily remove the session using H2 web console available at: http://localhost:8080/h2-console/ (use `jdbc:h2:mem:testdb` for JDBC URL)
|
||||
You can remove the session by using H2 web console available at: http://localhost:8080/h2-console/ (use `jdbc:h2:mem:testdb` for JDBC URL)
|
||||
|
||||
Now visit the application at http://localhost:8080/ and observe that the attribute we added is no longer displayed.
|
||||
Now you can visit the application at http://localhost:8080/ and observe that the attribute we added is no longer displayed.
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
Rob Winch
|
||||
:toc:
|
||||
|
||||
This guide describes how to use Spring Session to transparently leverage Redis to back a web application's `HttpSession` with XML based configuration.
|
||||
This guide describes how to use Spring Session to transparently leverage Redis to back a web application's `HttpSession` with XML-based configuration.
|
||||
|
||||
NOTE: The completed guide can be found in the <<httpsession-xml-sample, httpsession-xml sample application>>.
|
||||
NOTE: You can find the completed guide in the <<httpsession-xml-sample, httpsession-xml sample application>>.
|
||||
|
||||
== Updating Dependencies
|
||||
Before you use Spring Session, you must ensure to update your dependencies.
|
||||
If you are using Maven, ensure to add the following dependencies:
|
||||
Before you use Spring Session, you must update your dependencies.
|
||||
If you use Maven, you must add the following dependencies:
|
||||
|
||||
====
|
||||
.pom.xml
|
||||
[source,xml]
|
||||
[subs="verbatim,attributes"]
|
||||
@@ -35,11 +36,13 @@ If you are using Maven, ensure to add the following dependencies:
|
||||
</dependency>
|
||||
</dependencies>
|
||||
----
|
||||
====
|
||||
|
||||
ifeval::["{version-snapshot}" == "true"]
|
||||
Since we are using a SNAPSHOT version, we need to ensure to add the Spring Snapshot Maven Repository.
|
||||
Ensure you have the following in your pom.xml:
|
||||
Since we are using a SNAPSHOT version, we need to add the Spring Snapshot Maven Repository.
|
||||
You must have the following in your pom.xml:
|
||||
|
||||
====
|
||||
.pom.xml
|
||||
[source,xml]
|
||||
----
|
||||
@@ -53,12 +56,14 @@ Ensure you have the following in your pom.xml:
|
||||
</repository>
|
||||
</repositories>
|
||||
----
|
||||
====
|
||||
endif::[]
|
||||
|
||||
ifeval::["{version-milestone}" == "true"]
|
||||
Since We are using a Milestone version, we need to ensure to add the Spring Milestone Maven Repository.
|
||||
Ensure you have the following in your pom.xml:
|
||||
Since we are using a Milestone version, we need to add the Spring Milestone Maven Repository.
|
||||
You must have the following in your pom.xml:
|
||||
|
||||
====
|
||||
.pom.xml
|
||||
[source,xml]
|
||||
----
|
||||
@@ -67,6 +72,7 @@ Ensure you have the following in your pom.xml:
|
||||
<url>https://repo.spring.io/libs-milestone</url>
|
||||
</repository>
|
||||
----
|
||||
====
|
||||
endif::[]
|
||||
|
||||
// tag::config[]
|
||||
@@ -75,9 +81,10 @@ endif::[]
|
||||
== Spring XML Configuration
|
||||
|
||||
After adding the required dependencies, we can create our Spring configuration.
|
||||
The Spring configuration is responsible for creating a Servlet Filter that replaces the `HttpSession` implementation with an implementation backed by Spring Session.
|
||||
Add the following Spring Configuration:
|
||||
The Spring configuration is responsible for creating a servlet filter that replaces the `HttpSession` implementation with an implementation backed by Spring Session.
|
||||
To do so, add the following Spring Configuration:
|
||||
|
||||
====
|
||||
.src/main/webapp/WEB-INF/spring/session.xml
|
||||
[source,xml,indent=0]
|
||||
----
|
||||
@@ -85,12 +92,13 @@ include::{samples-dir}xml/redis/src/main/webapp/WEB-INF/spring/session.xml[tags=
|
||||
----
|
||||
|
||||
<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]).
|
||||
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.
|
||||
This creates a Spring Bean with the name of `springSessionRepositoryFilter` that implements `Filter`.
|
||||
The filter 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)
|
||||
For more information on configuring Spring Data Redis, refer to the https://docs.spring.io/spring-data/data-redis/docs/{spring-data-redis-version}/reference/html/[reference documentation].
|
||||
For more information on configuring Spring Data Redis, see the https://docs.spring.io/spring-data/data-redis/docs/{spring-data-redis-version}/reference/html/[reference documentation].
|
||||
====
|
||||
|
||||
== XML Servlet Container Initialization
|
||||
|
||||
@@ -98,83 +106,99 @@ Our <<httpsession-xml-spring-configuration,Spring Configuration>> created a Spri
|
||||
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, we need to instruct Spring to load our `session.xml` configuration.
|
||||
We do this with the following configuration:
|
||||
|
||||
We can do so with the following configuration:
|
||||
|
||||
====
|
||||
.src/main/webapp/WEB-INF/web.xml
|
||||
[source,xml,indent=0]
|
||||
----
|
||||
include::{samples-dir}xml/redis/src/main/webapp/WEB-INF/web.xml[tags=context-param]
|
||||
include::{samples-dir}xml/redis/src/main/webapp/WEB-INF/web.xml[tags=listeners]
|
||||
----
|
||||
====
|
||||
|
||||
The https://docs.spring.io/spring/docs/{spring-framework-version}/spring-framework-reference/core.html#context-create[ContextLoaderListener] reads the contextConfigLocation and picks up our session.xml configuration.
|
||||
The https://docs.spring.io/spring/docs/{spring-framework-version}/spring-framework-reference/core.html#context-create[`ContextLoaderListener`] reads the contextConfigLocation and picks up our session.xml configuration.
|
||||
|
||||
Last we need to ensure that our Servlet Container (i.e. Tomcat) uses our `springSessionRepositoryFilter` for every request.
|
||||
Last, we need to ensure that our Servlet Container (that is, Tomcat) uses our `springSessionRepositoryFilter` for every request.
|
||||
The following snippet performs this last step for us:
|
||||
|
||||
====
|
||||
.src/main/webapp/WEB-INF/web.xml
|
||||
[source,xml,indent=0]
|
||||
----
|
||||
include::{samples-dir}xml/redis/src/main/webapp/WEB-INF/web.xml[tags=springSessionRepositoryFilter]
|
||||
----
|
||||
====
|
||||
|
||||
The https://docs.spring.io/spring-framework/docs/{spring-framework-version}/javadoc-api/org/springframework/web/filter/DelegatingFilterProxy.html[DelegatingFilterProxy] will look up a Bean by the name of `springSessionRepositoryFilter` and cast it to a `Filter`.
|
||||
For every request that `DelegatingFilterProxy` is invoked, the `springSessionRepositoryFilter` will be invoked.
|
||||
The https://docs.spring.io/spring-framework/docs/{spring-framework-version}/javadoc-api/org/springframework/web/filter/DelegatingFilterProxy.html[`DelegatingFilterProxy`] looks up a Bean by the name of `springSessionRepositoryFilter` and cast it to a `Filter`.
|
||||
For every request that `DelegatingFilterProxy` is invoked, the `springSessionRepositoryFilter` is invoked.
|
||||
|
||||
// end::config[]
|
||||
|
||||
[[httpsession-xml-sample]]
|
||||
== httpsession-xml Sample Application
|
||||
== `httpsession-xml` Sample Application
|
||||
|
||||
=== Running the httpsession-xml Sample Application
|
||||
This section describes how to work with the `httpsession-xml` sample application.
|
||||
|
||||
=== Running the `httpsession-xml` Sample Application
|
||||
|
||||
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 https://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
|
||||
NOTE: For the sample to work, you must https://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
|
||||
Alternatively, you can update the `RedisConnectionFactory` to point to a Redis server.
|
||||
Another option is to use https://www.docker.com/[Docker] to run Redis on localhost. See https://hub.docker.com/_/redis/[Docker Redis repository] for detailed instructions.
|
||||
====
|
||||
|
||||
====
|
||||
----
|
||||
$ ./gradlew :spring-session-sample-xml-redis:tomcatRun
|
||||
----
|
||||
====
|
||||
|
||||
You should now be able to access the application at http://localhost:8080/
|
||||
|
||||
=== Exploring the httpsession-xml Sample Application
|
||||
=== Exploring the `httpsession-xml` Sample Application
|
||||
|
||||
Try using the application. Fill out the form with the following information:
|
||||
Now you can try using the application. Fill out the form with the following information:
|
||||
|
||||
* **Attribute Name:** _username_
|
||||
* **Attribute Value:** _rob_
|
||||
* *Attribute Name:* _username_
|
||||
* *Attribute Value:* _rob_
|
||||
|
||||
Now click the **Set Attribute** button. You should now see the values displayed in the table.
|
||||
Now click the *Set Attribute* button. You should now see the values displayed in the table.
|
||||
|
||||
=== How does it work?
|
||||
=== How Does It Work?
|
||||
|
||||
We interact with the standard `HttpSession` in the `SessionServlet` shown below:
|
||||
We interact with the standard `HttpSession` in the `SessionServlet` shown in the following listing:
|
||||
|
||||
====
|
||||
.src/main/java/sample/SessionServlet.java
|
||||
[source,java]
|
||||
----
|
||||
include::{samples-dir}xml/redis/src/main/java/sample/SessionServlet.java[tags=class]
|
||||
----
|
||||
====
|
||||
|
||||
Instead of using Tomcat's `HttpSession`, we are actually persisting the values in Redis.
|
||||
Spring Session creates a cookie named SESSION in your browser that contains the id of your session.
|
||||
Go ahead and view the cookies (click for help with https://developers.google.com/web/tools/chrome-devtools/manage-data/cookies[Chrome] or https://developer.mozilla.org/en-US/docs/Tools/Storage_Inspector[Firefox]).
|
||||
Instead of using Tomcat's `HttpSession`, we persist the values in Redis.
|
||||
Spring Session creates a cookie named SESSION in your browser.
|
||||
That cookie contains the ID of your session.
|
||||
You can view the cookies (with https://developers.google.com/web/tools/chrome-devtools/manage-data/cookies[Chrome] or https://developer.mozilla.org/en-US/docs/Tools/Storage_Inspector[Firefox]).
|
||||
|
||||
If you like, you can easily remove the session using redis-cli. For example, on a Linux based system you can type:
|
||||
You can remove the session using redis-cli.
|
||||
For example, on a Linux based system you can type the following:
|
||||
|
||||
====
|
||||
----
|
||||
$ redis-cli keys '*' | xargs redis-cli del
|
||||
----
|
||||
====
|
||||
|
||||
TIP: The Redis documentation has instructions for https://redis.io/topics/quickstart[installing redis-cli].
|
||||
|
||||
Alternatively, you can also delete the explicit key. Enter the following into your terminal ensuring to replace `7e8383a4-082c-4ffe-a4bc-c40fd3363c5e` with the value of your SESSION cookie:
|
||||
Alternatively, you can also delete the explicit key. To do so, enter the following into your terminal, being sure to replace `7e8383a4-082c-4ffe-a4bc-c40fd3363c5e` with the value of your SESSION cookie:
|
||||
|
||||
====
|
||||
----
|
||||
$ redis-cli del spring:session:sessions:7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
|
||||
----
|
||||
====
|
||||
|
||||
Now visit the application at http://localhost:8080/ and observe that the attribute we added is no longer displayed.
|
||||
Now you can visit the application at http://localhost:8080/ and see that the attribute we added is no longer displayed.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -24,7 +24,6 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||
import org.springframework.security.web.authentication.RememberMeServices;
|
||||
import org.springframework.session.MapSessionRepository;
|
||||
import org.springframework.session.config.annotation.web.http.EnableSpringHttpSession;
|
||||
import org.springframework.session.security.web.authentication.SpringSessionRememberMeServices;
|
||||
@@ -54,7 +53,7 @@ public class RememberMeSecurityConfiguration extends WebSecurityConfigurerAdapte
|
||||
|
||||
// tag::rememberme-bean[]
|
||||
@Bean
|
||||
RememberMeServices rememberMeServices() {
|
||||
public SpringSessionRememberMeServices rememberMeServices() {
|
||||
SpringSessionRememberMeServices rememberMeServices =
|
||||
new SpringSessionRememberMeServices();
|
||||
// optionally customize
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -30,10 +30,11 @@ import org.springframework.session.security.SpringSessionBackedSessionRegistry;
|
||||
*/
|
||||
// tag::class[]
|
||||
@Configuration
|
||||
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
public class SecurityConfiguration<S extends Session>
|
||||
extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Autowired
|
||||
private FindByIndexNameSessionRepository<Session> sessionRepository;
|
||||
private FindByIndexNameSessionRepository<S> sessionRepository;
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
@@ -47,7 +48,7 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
}
|
||||
|
||||
@Bean
|
||||
SpringSessionBackedSessionRegistry sessionRegistry() {
|
||||
public SpringSessionBackedSessionRegistry<S> sessionRegistry() {
|
||||
return new SpringSessionBackedSessionRegistry<>(this.sessionRepository);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:p="http://www.springframework.org/schema/p"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
|
||||
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd">
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
|
||||
http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util-4.1.xsd">
|
||||
|
||||
<context:annotation-config/>
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:p="http://www.springframework.org/schema/p"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
|
||||
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd">
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
|
||||
http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util-4.1.xsd">
|
||||
|
||||
<!-- tag::config[] -->
|
||||
<bean class="org.springframework.security.web.session.HttpSessionEventPublisher"/>
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:security="http://www.springframework.org/schema/security"
|
||||
xmlns:p="http://www.springframework.org/schema/p"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd
|
||||
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<!-- tag::config[] -->
|
||||
<security:http>
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:security="http://www.springframework.org/schema/security"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd">
|
||||
|
||||
<!-- tag::config[] -->
|
||||
<security:http>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
|
||||
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
|
||||
<!DOCTYPE module PUBLIC "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
|
||||
"https://checkstyle.org/dtds/configuration_1_3.dtd">
|
||||
<module name="Checker">
|
||||
<!-- Supressions -->
|
||||
<module name="SuppressionFilter">
|
||||
<property name="file" value="${configDir}/suppressions.xml"/>
|
||||
<property name="file" value="${config_loc}/suppressions.xml"/>
|
||||
</module>
|
||||
|
||||
<!-- Root Checks -->
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
^\Q/*\E$
|
||||
^\Q * Copyright 2014-\E20\d\d\Q the original author or authors.\E$
|
||||
^\Q *\E$
|
||||
^\Q * Licensed under the Apache License, Version 2.0 (the "License");\E$
|
||||
^\Q * you may not use this file except in compliance with the License.\E$
|
||||
^\Q * You may obtain a copy of the License at\E$
|
||||
^\Q *\E$
|
||||
^\Q * http://www.apache.org/licenses/LICENSE-2.0\E$
|
||||
^\Q *\E$
|
||||
^\Q * Unless required by applicable law or agreed to in writing, software\E$
|
||||
^\Q * distributed under the License is distributed on an "AS IS" BASIS,\E$
|
||||
^\Q * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\E$
|
||||
^\Q * See the License for the specific language governing permissions and\E$
|
||||
^\Q * limitations under the License.\E$
|
||||
^\Q */\E$
|
||||
^.*$
|
||||
@@ -1,16 +1,17 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE suppressions PUBLIC "-//Puppy Crawl//DTD Suppressions 1.1//EN"
|
||||
"http://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
|
||||
<!DOCTYPE suppressions PUBLIC "-//Checkstyle//DTD SuppressionFilter Configuration 1.2//EN"
|
||||
"https://checkstyle.org/dtds/suppressions_1_2.dtd">
|
||||
<suppressions>
|
||||
<!-- global -->
|
||||
<suppress files="[\\/]src[\\/]integration-test[\\/]java[\\/]" checks="Javadoc*"/>
|
||||
|
||||
<!-- docs -->
|
||||
<suppress files="[\\/]docs[\\/]" checks="Javadoc*"/>
|
||||
<suppress files="[\\/]docs[\\/]" checks="AvoidStaticImport"/>
|
||||
<suppress files="[\\/]docs[\\/]" checks="InnerTypeLast"/>
|
||||
|
||||
<!-- samples -->
|
||||
<suppress files="[\\/]samples[\\/]" checks="Javadoc*"/>
|
||||
<suppress files="[\\/]samples[\\/].+Application\.java" checks="HideUtilityClassConstructor"/>
|
||||
|
||||
<suppress files="SessionRepositoryFilterTests\.java" checks="SpringLambda"/>
|
||||
</suppressions>
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
springBootVersion=2.1.0.M1
|
||||
version=2.1.0.M2
|
||||
version=2.1.14.BUILD-SNAPSHOT
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
dependencyManagement {
|
||||
imports {
|
||||
mavenBom 'com.fasterxml.jackson:jackson-bom:2.9.6'
|
||||
mavenBom 'io.projectreactor:reactor-bom:Californium-M2'
|
||||
mavenBom 'org.springframework:spring-framework-bom:5.1.0.RC2'
|
||||
mavenBom 'org.springframework.data:spring-data-releasetrain:Lovelace-RC2'
|
||||
mavenBom 'org.springframework.security:spring-security-bom:5.1.0.RC1'
|
||||
mavenBom 'org.testcontainers:testcontainers-bom:1.8.3'
|
||||
mavenBom 'io.projectreactor:reactor-bom:Californium-SR21'
|
||||
mavenBom 'org.springframework:spring-framework-bom:5.1.18.RELEASE'
|
||||
mavenBom 'org.springframework.data:spring-data-releasetrain:Lovelace-SR20'
|
||||
mavenBom 'org.springframework.security:spring-security-bom:5.1.12.RELEASE'
|
||||
mavenBom 'org.testcontainers:testcontainers-bom:1.12.5'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
dependencySet(group: 'com.hazelcast', version: '3.10.4') {
|
||||
dependencySet(group: 'com.hazelcast', version: '3.11.4') {
|
||||
entry 'hazelcast'
|
||||
entry 'hazelcast-client'
|
||||
}
|
||||
|
||||
dependency 'com.h2database:h2:1.4.197'
|
||||
dependency 'com.microsoft.sqlserver:mssql-jdbc:7.0.0.jre8'
|
||||
dependency 'com.h2database:h2:1.4.200'
|
||||
dependency 'com.microsoft.sqlserver:mssql-jdbc:7.4.1.jre8'
|
||||
dependency 'com.zaxxer:HikariCP:3.4.5'
|
||||
dependency 'edu.umd.cs.mtc:multithreadedtc:1.01'
|
||||
dependency 'io.lettuce:lettuce-core:5.1.0.M1'
|
||||
dependency 'io.lettuce:lettuce-core:5.2.0.RELEASE'
|
||||
dependency 'javax.annotation:javax.annotation-api:1.3.2'
|
||||
dependency 'javax.servlet:javax.servlet-api:4.0.1'
|
||||
dependency 'junit:junit:4.12'
|
||||
dependency 'mysql:mysql-connector-java:8.0.12'
|
||||
dependency 'mysql:mysql-connector-java:8.0.21'
|
||||
dependency 'org.apache.derby:derby:10.14.2.0'
|
||||
dependency 'org.assertj:assertj-core:3.11.0'
|
||||
dependency 'org.hsqldb:hsqldb:2.4.1'
|
||||
dependency 'org.mariadb.jdbc:mariadb-java-client:2.2.6'
|
||||
dependency 'org.mockito:mockito-core:2.21.0'
|
||||
dependency 'org.postgresql:postgresql:42.2.4'
|
||||
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.0.0'
|
||||
dependency 'org.postgresql:postgresql:42.2.16'
|
||||
}
|
||||
}
|
||||
|
||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
* Copyright 2014-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -46,7 +46,7 @@ import org.springframework.test.web.servlet.htmlunit.webdriver.MockMvcHtmlUnitDr
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.MOCK)
|
||||
public class FindByUsernameTests {
|
||||
|
||||
private static final String DOCKER_IMAGE = "redis:4.0.11";
|
||||
private static final String DOCKER_IMAGE = "redis:5.0.6";
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
ryuk.container.timeout=120
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}">
|
||||
<html xmlns:th="https://www.thymeleaf.org" xmlns:layout="https://github.com/ultraq/thymeleaf-layout-dialect" layout:decorate="~{layout}">
|
||||
<head>
|
||||
<title>Secured Content</title>
|
||||
</head>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-3.dtd">
|
||||
<!DOCTYPE html SYSTEM "https://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-3.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
|
||||
xmlns:th="https://www.thymeleaf.org"
|
||||
xmlns:layout="https://github.com/ultraq/thymeleaf-layout-dialect">
|
||||
<head>
|
||||
<title layout:title-pattern="$LAYOUT_TITLE - $CONTENT_TITLE">Spring Session Sample</title>
|
||||
<link rel="icon" type="image/x-icon" th:href="@{/favicon.ico}" href="../static/favicon.ico"/>
|
||||
@@ -115,7 +115,7 @@
|
||||
|
||||
<div id="footer">
|
||||
<div class="container">
|
||||
<p class="muted credit">This product includes GeoLite2 data created by MaxMind, available from <a href="http://www.maxmind.com">http://www.maxmind.com</a>.</p>
|
||||
<p class="muted credit">This product includes GeoLite2 data created by MaxMind, available from <a href="https://www.maxmind.com">https://www.maxmind.com</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<html xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
<html xmlns:th="https://www.thymeleaf.org"
|
||||
xmlns:layout="https://github.com/ultraq/thymeleaf-layout-dialect"
|
||||
layout:decorate="~{layout}">
|
||||
<head>
|
||||
<title>Log In</title>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}">
|
||||
<html xmlns:th="https://www.thymeleaf.org" xmlns:layout="https://github.com/ultraq/thymeleaf-layout-dialect" layout:decorate="~{layout}">
|
||||
<head>
|
||||
<title>Secured Content</title>
|
||||
</head>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-3.dtd">
|
||||
<!DOCTYPE html SYSTEM "https://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-3.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
|
||||
xmlns:th="https://www.thymeleaf.org"
|
||||
xmlns:layout="https://github.com/ultraq/thymeleaf-layout-dialect">
|
||||
<head>
|
||||
<title layout:title-pattern="$LAYOUT_TITLE - $CONTENT_TITLE">Spring Session Sample</title>
|
||||
<link rel="icon" type="image/x-icon" th:href="@{/favicon.ico}" href="../static/favicon.ico"/>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
* Copyright 2014-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -50,7 +50,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
@AutoConfigureMockMvc
|
||||
public class HttpRedisJsonTest {
|
||||
|
||||
private static final String DOCKER_IMAGE = "redis:4.0.11";
|
||||
private static final String DOCKER_IMAGE = "redis:5.0.6";
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
* Copyright 2014-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -39,7 +39,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
@SpringBootTest
|
||||
public class RedisSerializerTest {
|
||||
|
||||
private static final String DOCKER_IMAGE = "redis:4.0.11";
|
||||
private static final String DOCKER_IMAGE = "redis:5.0.6";
|
||||
|
||||
@SpringSessionRedisOperations
|
||||
private RedisTemplate<Object, Object> sessionRedisTemplate;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
ryuk.container.timeout=120
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}">
|
||||
<html xmlns:th="https://www.thymeleaf.org" xmlns:layout="https://github.com/ultraq/thymeleaf-layout-dialect" layout:decorate="~{layout}">
|
||||
<head>
|
||||
<title>Home</title>
|
||||
</head>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-3.dtd">
|
||||
<!DOCTYPE html SYSTEM "https://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-3.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
|
||||
xmlns:th="https://www.thymeleaf.org"
|
||||
xmlns:layout="https://github.com/ultraq/thymeleaf-layout-dialect">
|
||||
<head>
|
||||
<title layout:title-pattern="$LAYOUT_TITLE - $CONTENT_TITLE">Spring Session Sample</title>
|
||||
<link rel="icon" type="image/x-icon" th:href="@{/favicon.ico}" href="../static/favicon.ico"/>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}">
|
||||
<html xmlns:th="https://www.thymeleaf.org" xmlns:layout="https://github.com/ultraq/thymeleaf-layout-dialect" layout:decorate="~{layout}">
|
||||
<head>
|
||||
<title>Login</title>
|
||||
</head>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
* Copyright 2014-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -45,7 +45,7 @@ import org.springframework.test.web.servlet.htmlunit.webdriver.MockMvcHtmlUnitDr
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.MOCK)
|
||||
public class BootTests {
|
||||
|
||||
private static final String DOCKER_IMAGE = "redis:4.0.11";
|
||||
private static final String DOCKER_IMAGE = "redis:5.0.6";
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
ryuk.container.timeout=120
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}">
|
||||
<html xmlns:th="https://www.thymeleaf.org" xmlns:layout="https://github.com/ultraq/thymeleaf-layout-dialect" layout:decorate="~{layout}">
|
||||
<head>
|
||||
<title>Secured Content</title>
|
||||
</head>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-3.dtd">
|
||||
<!DOCTYPE html SYSTEM "https://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-3.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
|
||||
xmlns:th="https://www.thymeleaf.org"
|
||||
xmlns:layout="https://github.com/ultraq/thymeleaf-layout-dialect">
|
||||
<head>
|
||||
<title layout:title-pattern="$LAYOUT_TITLE - $CONTENT_TITLE">Spring Session Sample</title>
|
||||
<link rel="icon" type="image/x-icon" th:href="@{/favicon.ico}" href="../static/favicon.ico"/>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
* Copyright 2014-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -47,7 +47,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
public class AttributeTests {
|
||||
|
||||
private static final String DOCKER_IMAGE = "redis:4.0.11";
|
||||
private static final String DOCKER_IMAGE = "redis:5.0.6";
|
||||
|
||||
@LocalServerPort
|
||||
private int port;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user