Simplify project structure
- harmonize module and directory names - optimize Gradle settings - remove unused Grails sample Resolves: #1447
This commit is contained in:
222
spring-session-docs/src/docs/asciidoc/guides/java-hazelcast.adoc
Normal file
222
spring-session-docs/src/docs/asciidoc/guides/java-hazelcast.adoc
Normal file
@@ -0,0 +1,222 @@
|
||||
= Spring Session and Spring Security with Hazelcast
|
||||
Tommy Ludwig; Rob Winch
|
||||
:toc:
|
||||
|
||||
This guide describes how to use Spring Session along with Spring Security when you use Hazelcast as your data store.
|
||||
It assumes that you have already applied Spring Security to your application.
|
||||
|
||||
NOTE: You cand find the completed guide in the <<hazelcast-spring-security-sample, Hazelcast Spring Security sample application>>.
|
||||
|
||||
== Updating 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"]
|
||||
----
|
||||
<dependencies>
|
||||
<!-- ... -->
|
||||
|
||||
<dependency>
|
||||
<groupId>com.hazelcast</groupId>
|
||||
<artifactId>hazelcast</artifactId>
|
||||
<version>{hazelcast-version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>{spring-framework-version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
----
|
||||
====
|
||||
|
||||
ifeval::["{version-snapshot}" == "true"]
|
||||
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]
|
||||
----
|
||||
<repositories>
|
||||
|
||||
<!-- ... -->
|
||||
|
||||
<repository>
|
||||
<id>spring-snapshot</id>
|
||||
<url>https://repo.spring.io/libs-snapshot</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
----
|
||||
====
|
||||
endif::[]
|
||||
|
||||
ifeval::["{version-milestone}" == "true"]
|
||||
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]
|
||||
----
|
||||
<repository>
|
||||
<id>spring-milestone</id>
|
||||
<url>https://repo.spring.io/libs-milestone</url>
|
||||
</repository>
|
||||
----
|
||||
====
|
||||
endif::[]
|
||||
|
||||
// tag::config[]
|
||||
|
||||
[[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.
|
||||
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 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, 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`.
|
||||
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 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 (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`.
|
||||
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`.
|
||||
|
||||
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:
|
||||
|
||||
====
|
||||
----
|
||||
$ ./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
|
||||
|
||||
You can now try using the application.
|
||||
To do so, enter the following to log in:
|
||||
|
||||
* *Username* _user_
|
||||
* *Password* _password_
|
||||
|
||||
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?
|
||||
|
||||
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 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]).
|
||||
|
||||
=== Interacting with the Data Store
|
||||
|
||||
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
|
||||
|
||||
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 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, 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 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 (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 is printed to the console on startup. Replace `xxxxx` with the port number.
|
||||
|
||||
Now you can see that you are no longer authenticated with this session.
|
||||
Reference in New Issue
Block a user