diff --git a/docs/modules/guides/pages/basic-auth.adoc b/docs/modules/guides/pages/basic-auth.adoc
index 812e8d28e..82be782a7 100644
--- a/docs/modules/guides/pages/basic-auth.adoc
+++ b/docs/modules/guides/pages/basic-auth.adoc
@@ -10,110 +10,36 @@ If you are new to Spring Security, this recipe is worth reviewing, to learn the
[[security-cookbook-the-web-application]]
== The Application to Secure
-Spring Security secures applications, so we need an application to secure.
-A simple web application suffices as an example that we can then secure in the various recipes.
-
-NOTE: We use the same example that we used in the "`Securing a Web Application`" guide, which you can find on the Spring web site at https://spring.io/guides/gs/securing-web/[https://spring.io/guides/gs/securing-web/].
-
-We use Spring Boot with the Spring Web and Thymeleaf dependencies.
-There are lots of ways to make a web application, but we know this one well, since we have documented it elsewhere.
+For this guide, we build an application from scratch with Spring Boot
+To do so, navigate to the https://start.spring.io[Spring Initializr] and add the Web and Thymeleaf dependencies.
-We start with the build files for both Maven and Gradle (in case you prefer one or the other).
-The following listing shows the build file for Maven (`pom.xml`):
+Alternatively, you can perform the following steps on the command line:
====
-[source,xml]
+.Gradle
+[source,shell]
----
-
-
- 4.0.0
-
- org.springframework.boot
- spring-boot-starter-parent
- 2.2.0.RELEASE
-
-
- com.example
- securing-web
- 0.0.1-SNAPSHOT
- securing-web
- Demo project for Spring Boot
-
-
- 1.8
-
-
-
-
- org.springframework.boot
- spring-boot-starter-thymeleaf
-
-
- org.springframework.boot
- spring-boot-starter-web
-
-
-
- org.springframework.boot
- spring-boot-starter-test
- test
-
-
- org.junit.vintage
- junit-vintage-engine
-
-
-
-
-
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
-
-
-
+$ curl -G https://start.spring.io/starter.tgz -d dependencies=web,thymeleaf -d name=basic-auth -d baseDir=basic-auth -d type=gradle-project | tar -xzvf -
----
-====
-The following listing shows the build file for Gradle (`build.gradle`):
-
-====
-[source,java]
+.Maven
+[source,shell]
----
-plugins {
- id 'org.springframework.boot' version '2.2.0.RELEASE'
- id 'io.spring.dependency-management' version '1.0.8.RELEASE'
- id 'java'
-}
-
-group = 'com.example'
-version = '0.0.1-SNAPSHOT'
-sourceCompatibility = '1.8'
-
-repositories {
- mavenCentral()
-}
-
-dependencies {
- implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
- implementation 'org.springframework.boot:spring-boot-starter-web'
- testImplementation('org.springframework.boot:spring-boot-starter-test') {
- exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
- }
-}
-
-test {
- useJUnitPlatform()
-}
+$ curl -G https://start.spring.io/starter.tgz -d dependencies=web,thymeleaf -d name=basic-auth -d baseDir=basic-auth -d type=maven-project | tar -xzvf -
----
====
-After the build files, we need some HTML files.
+You can then import that project into your favorite IDE or work directly with the files and `./mvnw` or `./gradlew` on the command line.
+
+Spring Security secures applications, so we need an application to secure.
+A simple web application suffices as an example that we can then secure in the various recipes.
+
+NOTE: We use the same example that we used in the "`Securing a Web Application`" guide, which you can find on the Spring web site at https://spring.io/guides/gs/securing-web/[https://spring.io/guides/gs/securing-web/].
+
+We use Spring Boot with the Spring Web and Thymeleaf dependencies.
+There are lots of ways to make a web application, but we know this one well, since we have documented it elsewhere.
+
+We need some HTML files.
We start where a visitor would start, at `home.html`.
IMPORTANT: The HTML files go in the `resources/templates` directory.
@@ -124,86 +50,28 @@ The following listing shows our `home.html` file:
====
[source,html]
----
-
-
-
-
-
+include::../../../../servlet/spring-boot/java/basic-auth/src/main/resources/templates/home.html[]
----
====
We also need a `hello.html` file, so that visitors to our web site can see the greeting we mention in the `home.html` file.
-The following listing shows the `home.html` file:
+The following listing shows the `hello.html` file:
-====
[source,html]
-----
-
-
-
- Hello, World!
-
-
-
Hello, world!
-
-
-----
-====
-
-Once we have HTML pages for our visitors to see, we need to route them to the pages.
-We do that with a class that implements the `WebMvcConfigurer` (from the Spring framework).
-The following listing shows that class, which is called `MvcConfig`:
-
====
-[source,java]
----
-package com.example.securingweb;
-
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-
-@Configuration
-public class MvcConfig implements WebMvcConfigurer {
-
- public void addViewControllers(ViewControllerRegistry registry) {
- registry.addViewController("/home").setViewName("home");
- registry.addViewController("/").setViewName("home");
- registry.addViewController("/hello").setViewName("hello");
- }
-
-}
+include::../../../../servlet/spring-boot/java/basic-auth/src/main/resources/templates/hello.html[]
----
====
-Finally, we need an application class to give us an entry point for our program.
-We call it `SecuringWebApplication`, even though it is not yet secure.
-We cover how to secure it in the various recipes.
-The following application shows the `SecuringWebApplication` class:
+Once we have HTML pages for our visitors to see, we need to route them to the pages.
+We do that with a class that uses the `@Controller` annotation (from the Spring framework).
+The following listing shows that class, which is called `HelloController`:
====
[source,java]
----
-package com.example.securingweb;
-
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-
-@SpringBootApplication
-public class SecuringWebApplication {
-
- public static void main(String[] args) throws Throwable {
- SpringApplication.run(SecuringWebApplication.class, args);
- }
-
-}
+include::../../../../servlet/spring-boot/java/basic-auth/src/main/java/example/HelloController.java[tag=sans-header]
----
====
@@ -224,41 +92,6 @@ implementation 'org.springframework.security:spring-security-test'
----
====
-The following listing shows the final `build.gradle` file:
-
-====
-[source,java]
-----
-plugins {
- id 'org.springframework.boot' version '2.2.0.RELEASE'
- id 'io.spring.dependency-management' version '1.0.8.RELEASE'
- id 'java'
-}
-
-group = 'com.example'
-version = '0.0.1-SNAPSHOT'
-sourceCompatibility = '1.8'
-
-repositories {
- mavenCentral()
-}
-
-dependencies {
- implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
- implementation 'org.springframework.boot:spring-boot-starter-web'
- implementation 'org.springframework.boot:spring-boot-starter-security'
- implementation 'org.springframework.security:spring-security-test'
- testImplementation('org.springframework.boot:spring-boot-starter-test') {
- exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
- }
-}
-
-test {
- useJUnitPlatform()
-}
-----
-====
-
For Maven, we need to add the following two dependencies to the `dependencies` element in our `pom.xml` file:
====
@@ -276,199 +109,53 @@ For Maven, we need to add the following two dependencies to the `dependencies` e
----
====
-The following listing shows the final `pom.xml` file:
-
-====
-[source,xml]
-----
-
-
- 4.0.0
-
- org.springframework.boot
- spring-boot-starter-parent
- 2.2.0.RELEASE
-
-
- com.example
- securing-web
- 0.0.1-SNAPSHOT
- securing-web
- Demo project for Spring Boot
-
-
- 1.8
-
-
-
-
- org.springframework.boot
- spring-boot-starter-thymeleaf
-
-
- org.springframework.boot
- spring-boot-starter-web
-
-
- org.springframework.boot
- spring-boot-starter-security
-
-
- org.springframework.security
- spring-security-test
- test
-
-
-
- org.springframework.boot
- spring-boot-starter-test
- test
-
-
- org.junit.vintage
- junit-vintage-engine
-
-
-
-
-
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
-
-
-
-----
-====
-
We also need a login page. The following HTML file serves that need:
====
[source,html]
----
-
-
-
- Spring Security Example
-
-
-
- Invalid username and password.
-
-
- You have been logged out.
-
-
-
-
+include::../../../../servlet/spring-boot/java/basic-auth/src/main/resources/templates/login.html[]
----
====
-We also need to add a line to our `MvcConfig` class, as the following listing shows:
+We also need to add another class to our application, as the following listing shows:
====
[source,java]
----
-package com.example.securingweb;
-
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-
-@Configuration
-public class MvcConfig implements WebMvcConfigurer {
-
- public void addViewControllers(ViewControllerRegistry registry) {
- registry.addViewController("/home").setViewName("home");
- registry.addViewController("/").setViewName("home");
- registry.addViewController("/hello").setViewName("hello");
- registry.addViewController("/login").setViewName("login"); <1>
- }
-
-}
+include::../../../../servlet/spring-boot/java/basic-auth/src/main/java/example/LoginController.java[tag=sans-header]
----
-<1> We need to add this line to make the `/login` path work.
+<1> We need to add this class to make the `/login` path work.
====
We also need a class to configure security for our web application.
-The following listing shows that class (called `WebSecurityConfig`):
+The following listing shows that class (called `SecurityConfiguration`):
====
[source,java]
----
-package com.example.securingweb;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.security.config.annotation.web.builders.HttpSecurity;
-import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
-import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
-import org.springframework.security.core.userdetails.User;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.security.core.userdetails.UserDetailsService;
-import org.springframework.security.provisioning.InMemoryUserDetailsManager;
-
-@Configuration
-@EnableWebSecurity
-public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
- @Override
- protected void configure(HttpSecurity http) throws Exception {
- http
- .authorizeRequests() <1>
- .antMatchers("/", "/home").permitAll() <2>
- .anyRequest().authenticated() <3>
- .and()
- .formLogin() <4>
- .loginPage("/login") <5>
- .permitAll()
- .and()
- .logout() <6>
- .permitAll();
- }
-
- @Bean
- @Override
- public UserDetailsService userDetailsService() {
- UserDetails user = <7>
- User.withDefaultPasswordEncoder()
- .username("user") <8>
- .password("password") <9>
- .roles("USER") <10>
- .build(); <11>
-
- return new InMemoryUserDetailsManager(user);
- }
-}
+include::../../../../servlet/spring-boot/java/basic-auth/src/main/java/example/SecurityConfiguration.java[tag=sans-header]
----
-<1> Turn on security by authorizing request.
+<1> Turn on security by authorizing the request.
<2> Let anyone see the default and `home` paths.
<3> Require that any request be authenticated. (This is where we apply security.)
<4> Allow a login form.
<5> Allow that form from the `/login` path.
-<6> Let anyone see the logout page.
+<6> Let anyone see the logout success page.
<7> Define a user object.
-<8> The user's user name is `user`.
-<9> The user's user name is `password`.
-<10> The user's role is `USER`.
-<11> Build the user object.
+<8> Encode the password in memory (used only for demonstration purposes -- do NOT do this in production).
+<9> The user's user name is `user`.
+<10> The user's password is `password`.
+<11> The user's role is `USER`.
+<12> Build the user object.
====
WARNING: _NEVER_ put user names and passwords in code for a real application.
It is tolerable for demonstrations and samples, but it is very poor practice for real applications.
-The `WebSecurityConfig` class has two key parts: A `configure` method (which overrides the `configure` method in `WebSecurityConfigurerAdapter`) and a `UserDetailsService` bean.
+The `SecurityConfiguration` class has two key parts: a `configure` method (which overrides the `configure` method in `WebSecurityConfigurerAdapter`) and a `UserDetailsService` bean.
The `configure` method has a chain of methods that define the security for the paths in our application.
-In essence, the preceding configuration says, "`Let anyone see the login and logout pages. Make everyone authenticate (log in) to see anything else.`"
+In essence, the preceding configuration says, "`Let anyone see the login and logout pages, as well as the home page. Make everyone authenticate (log in) to see anything else.`"
We also define the one and only user who can view our web application.
-Normally, we would get user details from a database or an LDAP or OAuth server (or from some other source - many options exist).
+Normally, we would get user details from a database or an LDAP or OAuth server (or from some other source -- the other Spring Security guides cover the most common ways to get user details).
We created this simple arrangement to show the basic outline of what happens.
diff --git a/servlet/spring-boot/java/basic-auth/build.gradle b/servlet/spring-boot/java/basic-auth/build.gradle
new file mode 100644
index 000000000..e2db7a5d4
--- /dev/null
+++ b/servlet/spring-boot/java/basic-auth/build.gradle
@@ -0,0 +1,25 @@
+plugins {
+ id 'io.spring.dependency-management' version '1.0.10.RELEASE'
+ id 'org.springframework.boot' version '2.5.2'
+ id "nebula.integtest" version "8.2.0"
+ id 'java'
+}
+
+repositories {
+ jcenter()
+ maven { url "https://repo.spring.io/snapshot" }
+}
+
+dependencies {
+ implementation 'org.springframework.boot:spring-boot-starter-security'
+ implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
+ implementation 'org.springframework.boot:spring-boot-starter-web'
+
+ testImplementation 'org.springframework.boot:spring-boot-starter-test'
+ testImplementation 'org.springframework.security:spring-security-test'
+}
+
+tasks.withType(Test).configureEach {
+ useJUnitPlatform()
+ outputs.upToDateWhen { false }
+}
diff --git a/servlet/spring-boot/java/basic-auth/gradle.properties b/servlet/spring-boot/java/basic-auth/gradle.properties
new file mode 100644
index 000000000..e19a862c9
--- /dev/null
+++ b/servlet/spring-boot/java/basic-auth/gradle.properties
@@ -0,0 +1,2 @@
+version=5.7.0-SNAPSHOT
+spring-security.version=5.7.0-SNAPSHOT
diff --git a/servlet/spring-boot/java/basic-auth/gradle/wrapper/gradle-wrapper.jar b/servlet/spring-boot/java/basic-auth/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 000000000..62d4c0535
Binary files /dev/null and b/servlet/spring-boot/java/basic-auth/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/servlet/spring-boot/java/basic-auth/gradle/wrapper/gradle-wrapper.properties b/servlet/spring-boot/java/basic-auth/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 000000000..ffed3a254
--- /dev/null
+++ b/servlet/spring-boot/java/basic-auth/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/servlet/spring-boot/java/basic-auth/gradlew b/servlet/spring-boot/java/basic-auth/gradlew
new file mode 100755
index 000000000..fbd7c5158
--- /dev/null
+++ b/servlet/spring-boot/java/basic-auth/gradlew
@@ -0,0 +1,185 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# 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,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=`expr $i + 1`
+ done
+ case $i in
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+exec "$JAVACMD" "$@"
diff --git a/servlet/spring-boot/java/basic-auth/gradlew.bat b/servlet/spring-boot/java/basic-auth/gradlew.bat
new file mode 100644
index 000000000..5093609d5
--- /dev/null
+++ b/servlet/spring-boot/java/basic-auth/gradlew.bat
@@ -0,0 +1,104 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/servlet/spring-boot/java/basic-auth/settings.gradle b/servlet/spring-boot/java/basic-auth/settings.gradle
new file mode 100644
index 000000000..8b1378917
--- /dev/null
+++ b/servlet/spring-boot/java/basic-auth/settings.gradle
@@ -0,0 +1 @@
+
diff --git a/servlet/spring-boot/java/basic-auth/src/main/java/example/BasicAuthApplication.java b/servlet/spring-boot/java/basic-auth/src/main/java/example/BasicAuthApplication.java
new file mode 100644
index 000000000..fd2ef3a7c
--- /dev/null
+++ b/servlet/spring-boot/java/basic-auth/src/main/java/example/BasicAuthApplication.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2012-2021 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
+ *
+ * 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,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package example;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * Basic Auth application.
+ *
+ * @author Steve Riesenberg
+ */
+@SpringBootApplication
+public class BasicAuthApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(BasicAuthApplication.class, args);
+ }
+
+}
diff --git a/servlet/spring-boot/java/basic-auth/src/main/java/example/HelloController.java b/servlet/spring-boot/java/basic-auth/src/main/java/example/HelloController.java
new file mode 100644
index 000000000..356668f39
--- /dev/null
+++ b/servlet/spring-boot/java/basic-auth/src/main/java/example/HelloController.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 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
+ *
+ * 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,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+// tag::sans-header[]
+package example;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+
+/**
+ * Controller for home and hello resources.
+ *
+ * @author Steve Riesenberg
+ */
+@Controller
+public class HelloController {
+
+ @GetMapping({"/", "/home"})
+ public String home() {
+ return "home";
+ }
+
+ @GetMapping("/hello")
+ public String hello() {
+ return "hello";
+ }
+
+}
+// end::sans-header[]
diff --git a/servlet/spring-boot/java/basic-auth/src/main/java/example/LoginController.java b/servlet/spring-boot/java/basic-auth/src/main/java/example/LoginController.java
new file mode 100644
index 000000000..5d1a7e728
--- /dev/null
+++ b/servlet/spring-boot/java/basic-auth/src/main/java/example/LoginController.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2021 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
+ *
+ * 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,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+// tag::sans-header[]
+package example;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+
+/**
+ * Controller for login page.
+ *
+ * @author Steve Riesenberg
+ */
+@Controller
+public class LoginController { // <1>
+
+ @GetMapping("/login")
+ public String login() {
+ return "login";
+ }
+
+}
+//end::sans-header[]
diff --git a/servlet/spring-boot/java/basic-auth/src/main/java/example/SecurityConfiguration.java b/servlet/spring-boot/java/basic-auth/src/main/java/example/SecurityConfiguration.java
new file mode 100644
index 000000000..e3fb7f033
--- /dev/null
+++ b/servlet/spring-boot/java/basic-auth/src/main/java/example/SecurityConfiguration.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2021 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
+ *
+ * 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,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+// tag::sans-header[]
+package example;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configurers.LogoutConfigurer;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.provisioning.InMemoryUserDetailsManager;
+import org.springframework.security.web.SecurityFilterChain;
+
+/**
+ * Spring Security configuration.
+ *
+ * @author Steve Riesenberg
+ */
+@EnableWebSecurity
+public class SecurityConfiguration {
+
+ @Bean
+ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
+ // @formatter:off
+ http
+ .authorizeHttpRequests((authorize) -> authorize // <1>
+ .mvcMatchers("/", "/home").permitAll() // <2>
+ .anyRequest().authenticated() // <3>
+ )
+ .formLogin((formLogin) -> formLogin // <4>
+ .loginPage("/login") // <5>
+ .permitAll()
+ )
+ .logout(LogoutConfigurer::permitAll); // <6>
+ // @formatter:on
+
+ return http.build();
+ }
+
+ @Bean
+ public UserDetailsService userDetailsService() {
+ // @formatter:off
+ UserDetails userDetails = // <7>
+ User.withDefaultPasswordEncoder() // <8>
+ .username("user") // <9>
+ .password("password") // <10>
+ .roles("USER") // <11>
+ .build(); // <12>
+ // @formatter:on
+
+ return new InMemoryUserDetailsManager(userDetails);
+ }
+
+}
+// end::sans-header[]
diff --git a/servlet/spring-boot/java/basic-auth/src/main/resources/templates/hello.html b/servlet/spring-boot/java/basic-auth/src/main/resources/templates/hello.html
new file mode 100644
index 000000000..6c6970d88
--- /dev/null
+++ b/servlet/spring-boot/java/basic-auth/src/main/resources/templates/hello.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+ Hello, World!
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/servlet/spring-boot/java/basic-auth/src/main/resources/templates/home.html b/servlet/spring-boot/java/basic-auth/src/main/resources/templates/home.html
new file mode 100644
index 000000000..1d9ddf130
--- /dev/null
+++ b/servlet/spring-boot/java/basic-auth/src/main/resources/templates/home.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+ Spring Security Example
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/servlet/spring-boot/java/basic-auth/src/main/resources/templates/login.html b/servlet/spring-boot/java/basic-auth/src/main/resources/templates/login.html
new file mode 100644
index 000000000..1dbb61be9
--- /dev/null
+++ b/servlet/spring-boot/java/basic-auth/src/main/resources/templates/login.html
@@ -0,0 +1,31 @@
+
+
+
+
+
+ Spring Security Example
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
index d690f206e..583730d1d 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -42,6 +42,7 @@ include ":servlet:java-configuration:max-sessions"
//include ":servlet:java-configuration:saml2:login"
include ":servlet:spring-boot:java:authentication:username-password:user-details-service:custom-user"
include ":servlet:spring-boot:java:authentication:username-password:mfa"
+include ":servlet:spring-boot:java:basic-auth"
include ":servlet:spring-boot:java:hello"
include ":servlet:spring-boot:java:hello-security"
include ":servlet:spring-boot:java:hello-security-explicit"