Compare commits
102 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
6e6ec5845e | ||
|
70891cd497 | ||
|
738463be8c | ||
|
26b20435c7 | ||
|
0d2c94c1d8 | ||
|
13c2ee4dd7 | ||
|
db4ff2eb77 | ||
|
4c2fcd0863 | ||
|
b59fdda518 | ||
|
b047d4f7ff | ||
|
44c9bd050f | ||
|
2df5617803 | ||
|
d3ed41d5ee | ||
|
e6c04b8f0e | ||
|
f27c00cbfa | ||
|
f1764e06c6 | ||
|
83e593b71c | ||
|
aafe457420 | ||
|
c0d5ff70fc | ||
|
6bed57d79b | ||
|
46db71921d | ||
|
e96d4cf602 | ||
|
33c5cb8bf8 | ||
|
dac72b8cce | ||
|
28a4a94b9a | ||
|
c2f34ad1de | ||
|
655cf77ea4 | ||
|
58e53e3e8e | ||
|
4819b13ada | ||
|
b42984ef8b | ||
|
2347dd638a | ||
|
554f1961db | ||
|
162ee60efb | ||
|
bc3fc6b2e0 | ||
|
cbbf5bb4bb | ||
|
6892a95805 | ||
|
cadaa9ac4f | ||
|
2b7ce67ff5 | ||
|
ebf0e1f181 | ||
|
2ffc2dd22a | ||
|
6a91568319 | ||
|
551f715b7c | ||
|
cb4bd098e3 | ||
|
bce2126fd1 | ||
|
545ffedea3 | ||
|
55e14fcb86 | ||
|
57c0b8a4c4 | ||
|
3dd832f99f | ||
|
e995914653 | ||
|
a4cef77512 | ||
|
c5a2162b07 | ||
|
f1c448becc | ||
|
dec2e57170 | ||
|
070916cbcd | ||
|
15adedbf87 | ||
|
7058a3592c | ||
|
2a9a874d41 | ||
|
7d80162ab9 | ||
|
f4afba567a | ||
|
a6e0f60def | ||
|
75f86c51ec | ||
|
fe037cf4d7 | ||
|
b2ec34de55 | ||
|
91a69b36f9 | ||
|
7b653aab91 | ||
|
a43cbcab41 | ||
|
6a60e655e3 | ||
|
ca32d8e45d | ||
|
3a58daf55d | ||
|
3a4eec6eda | ||
|
5354f8b349 | ||
|
482dfc9a59 | ||
|
7426260ee1 | ||
|
313dbd7a18 | ||
|
b48c07d36d | ||
|
ca19311b20 | ||
|
7d915468ae | ||
|
6dc97460c8 | ||
|
5097f9dcfc | ||
|
76d4b1e5a3 | ||
|
c4eaac0423 | ||
|
52cc331d9c | ||
|
6548ff0876 | ||
|
bf1ca80a0a | ||
|
aae31aee16 | ||
|
cbd87c4e04 | ||
|
f3348eec4a | ||
|
c35ba7bf5d | ||
|
4ccd5ce84b | ||
|
1ad87dcaf5 | ||
|
67f36c5862 | ||
|
def1af3e75 | ||
|
cb5b762681 | ||
|
f6439ddba8 | ||
|
15eaf5377b | ||
|
c9ed471e8d | ||
|
2ad47fdc67 | ||
|
789a203355 | ||
|
10b517f7b6 | ||
|
2396aa4630 | ||
|
868fb455c8 | ||
|
601f54a4c1 |
@ -16,7 +16,7 @@ jobs:
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: '8'
|
||||
java-version: '17'
|
||||
- name: Cache Gradle packages
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -73,6 +73,7 @@ local.properties
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff
|
||||
.idea/**/libraries-with-intellij-classes.xml
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/**/usage.statistics.xml
|
||||
|
4
.idea/misc.xml
generated
4
.idea/misc.xml
generated
@ -4,5 +4,5 @@
|
||||
<component name="FrameworkDetectionExcludesConfiguration">
|
||||
<file type="web" url="file://$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="11" project-jdk-type="JavaSDK" />
|
||||
</project>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="temurin-17" project-jdk-type="JavaSDK" />
|
||||
</project>
|
||||
|
68
README.adoc
68
README.adoc
@ -1,3 +1,71 @@
|
||||
image::https://github.com/spring-projects/spring-security-samples/workflows/CI/badge.svg[link=https://github.com/spring-projects/spring-security-samples/actions?query=workflow%3ACI]
|
||||
|
||||
Samples for https://github.com/spring-projects/spring-security
|
||||
|
||||
== Samples catalog
|
||||
|
||||
=== Getting Started
|
||||
|
||||
* Hello Security - https://github.com/spring-projects/spring-security-samples/tree/main/servlet/spring-boot/java/hello-security[Spring Boot] | https://github.com/spring-projects/spring-security-samples/tree/main/reactive/webflux/java/hello-security[WebFlux] | https://github.com/spring-projects/spring-security-samples/tree/main/reactive/webflux-fn/hello-security[WebFlux.fn] | https://github.com/spring-projects/spring-security-samples/tree/main/servlet/java-configuration/hello-security[Java Configuration] | https://github.com/spring-projects/spring-security-samples/tree/main/servlet/xml/java/helloworld[XML] | https://github.com/spring-projects/spring-security-samples/tree/main/servlet/spring-boot/kotlin/hello-security[Kotlin] | https://github.com/spring-projects/spring-security-samples/tree/main/reactive/webflux/kotlin/hello-security[WebFlux Kotlin] | https://github.com/spring-projects/spring-security-samples/tree/main/reactive/rsocket/hello-security[RSocket]
|
||||
|
||||
* Hello Security (without Spring MVC) - https://github.com/spring-projects/spring-security-samples/tree/main/servlet/java-configuration/hello-security-explicit[Java Configuration]
|
||||
|
||||
* Hello Security with Explicit Configuration - https://github.com/spring-projects/spring-security-samples/tree/main/servlet/spring-boot/java/hello-security-explicit[Spring Boot] | https://github.com/spring-projects/spring-security-samples/tree/main/reactive/webflux/java/hello-security-explicit[WebFlux] | https://github.com/spring-projects/spring-security-samples/tree/main/servlet/java-configuration/hello-mvc-security[Java Configuration]
|
||||
|
||||
* Method Security - https://github.com/spring-projects/spring-security-samples/tree/main/reactive/webflux/java/method[WebFlux]
|
||||
|
||||
* Spring Data Integration - https://github.com/spring-projects/spring-security-samples/tree/main/servlet/java-configuration/data[Java Configuration]
|
||||
|
||||
* Max Sessions - https://github.com/spring-projects/spring-security-samples/tree/main/servlet/java-configuration/max-sessions[Java Configuration]
|
||||
|
||||
* AspectJ Security Configuration - https://github.com/spring-projects/spring-security-samples/tree/main/servlet/java-configuration/aspectj[Java Configuration]
|
||||
|
||||
=== OAuth 2.0
|
||||
|
||||
* https://github.com/spring-projects/spring-security-samples/tree/main/servlet/spring-boot/java/oauth2/authorization-server[Authorization Server]
|
||||
|
||||
* Login - https://github.com/spring-projects/spring-security-samples/tree/main/servlet/spring-boot/java/oauth2/login[Spring Boot] | https://github.com/spring-projects/spring-security-samples/tree/main/reactive/webflux/java/oauth2/login[WebFlux]
|
||||
|
||||
* Resource Server
|
||||
|
||||
** Hello Security - https://github.com/spring-projects/spring-security-samples/tree/main/servlet/spring-boot/java/oauth2/resource-server/hello-security[Spring Boot] | https://github.com/spring-projects/spring-security-samples/tree/main/reactive/webflux/java/oauth2/resource-server[WebFlux]
|
||||
|
||||
** https://github.com/spring-projects/spring-security-samples/tree/main/servlet/spring-boot/java/oauth2/resource-server/jwe[JSON Web Encryption (JWE)]
|
||||
|
||||
** https://github.com/spring-projects/spring-security-samples/tree/main/servlet/spring-boot/java/oauth2/resource-server/multi-tenancy[Multi-tenancy]
|
||||
|
||||
** https://github.com/spring-projects/spring-security-samples/tree/main/servlet/spring-boot/java/oauth2/resource-server/opaque[Opaque Token]
|
||||
|
||||
** https://github.com/spring-projects/spring-security-samples/tree/main/servlet/spring-boot/java/oauth2/resource-server/static[Static]
|
||||
|
||||
* WebClient - https://github.com/spring-projects/spring-security-samples/tree/main/servlet/spring-boot/java/oauth2/webclient[Spring Boot] | https://github.com/spring-projects/spring-security-samples/tree/main/reactive/webflux/java/oauth2/webclient[WebFlux]
|
||||
|
||||
=== SAML 2.0
|
||||
|
||||
* Login & Logout - https://github.com/spring-projects/spring-security-samples/tree/main/servlet/spring-boot/java/saml2/login[Spring Boot] | https://github.com/spring-projects/spring-security-samples/tree/main/servlet/java-configuration/saml2/login[Java Configuration]
|
||||
|
||||
=== Authentication
|
||||
|
||||
* https://github.com/spring-projects/spring-security-samples/tree/main/servlet/java-configuration/authentication/preauth[Pre-authentication]
|
||||
|
||||
* https://github.com/spring-projects/spring-security-samples/tree/main/servlet/java-configuration/authentication/remember-me[Remember-me]
|
||||
|
||||
* Username and password
|
||||
|
||||
** Form Login - https://github.com/spring-projects/spring-security-samples/tree/main/servlet/java-configuration/authentication/username-password/form[Java Configuration] | https://github.com/spring-projects/spring-security-samples/tree/main/reactive/webflux/java/authentication/username-password/form[WebFlux]
|
||||
|
||||
** https://github.com/spring-projects/spring-security-samples/tree/main/servlet/java-configuration/authentication/username-password/in-memory[In-memory `UserDetailsService`]
|
||||
|
||||
** https://github.com/spring-projects/spring-security-samples/tree/main/servlet/java-configuration/authentication/username-password/jdbc[JDBC]
|
||||
|
||||
** https://github.com/spring-projects/spring-security-samples/tree/main/servlet/java-configuration/authentication/username-password/ldap[LDAP]
|
||||
|
||||
** https://github.com/spring-projects/spring-security-samples/tree/main/servlet/spring-boot/java/authentication/username-password/mfa[Multi-factor authentication]
|
||||
|
||||
** https://github.com/spring-projects/spring-security-samples/tree/main/servlet/spring-boot/java/authentication/username-password/user-details-service/custom-user[Custom `UserDetails`]
|
||||
|
||||
* X.509 - https://github.com/spring-projects/spring-security-samples/tree/main/servlet/java-configuration/authentication/x509[Java Configuration] | https://github.com/spring-projects/spring-security-samples/tree/main/reactive/webflux/java/authentication/x509[WebFlux]
|
||||
|
||||
=== JWT
|
||||
|
||||
* Login - https://github.com/spring-projects/spring-security-samples/tree/main/servlet/spring-boot/java/jwt/login[Spring Boot]
|
||||
|
24
build.gradle
24
build.gradle
@ -20,4 +20,26 @@ allprojects {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasProperty('buildScan')) {
|
||||
buildScan {
|
||||
termsOfServiceUrl = 'https://gradle.com/terms-of-service'
|
||||
termsOfServiceAgree = 'yes'
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
tasks.register('runAllTests') {
|
||||
var allTasks = rootProject.getAllTasks(true)
|
||||
var allTestsTasks = allTasks.values().collect { t ->
|
||||
t.findAll { it.name == 'test' || it.name == 'integrationTest' }
|
||||
}.flatten()
|
||||
it.dependsOn {
|
||||
allTestsTasks
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
version=5.5.0-SNAPSHOT
|
||||
spring-security.version=5.5.0-SNAPSHOT
|
||||
org.gradle.jvmargs=-Xmx3g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError
|
||||
version=6.0.0-SNAPSHOT
|
||||
spring-security.version=6.0.0-SNAPSHOT
|
||||
org.gradle.jvmargs=-Xmx3g -XX:+HeapDumpOnOutOfMemoryError
|
||||
org.gradle.parallel=true
|
||||
org.gradle.caching=true
|
||||
|
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-6.9-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
269
gradlew
vendored
269
gradlew
vendored
@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env sh
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright 2015 the original author or authors.
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@ -17,67 +17,101 @@
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# 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
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
APP_BASE_NAME=${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"
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
} >&2
|
||||
|
||||
# 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
|
||||
;;
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
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"
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
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
|
||||
@ -106,80 +140,95 @@ 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" ;;
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
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, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# 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"
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
# double quotes to make sure that they get re-expanded; and
|
||||
# * put everything else in single quotes, so that it's not re-expanded.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
|
21
gradlew.bat
vendored
21
gradlew.bat
vendored
@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
@ -54,7 +54,7 @@ goto fail
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
@ -64,21 +64,6 @@ 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
|
||||
|
||||
@ -86,7 +71,7 @@ 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%
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
|
@ -1,12 +1,13 @@
|
||||
plugins {
|
||||
id 'org.springframework.boot' version '2.5.0'
|
||||
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
|
||||
id "nebula.integtest" version "7.0.9"
|
||||
id 'org.springframework.boot' version '3.0.0-SNAPSHOT'
|
||||
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
|
||||
id "nebula.integtest" version "8.2.0"
|
||||
id 'java'
|
||||
}
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
maven { url "https://repo.spring.io/milestone" }
|
||||
maven { url "https://repo.spring.io/snapshot" }
|
||||
}
|
||||
|
||||
@ -21,4 +22,5 @@ dependencies {
|
||||
|
||||
tasks.withType(Test).configureEach {
|
||||
useJUnitPlatform()
|
||||
outputs.upToDateWhen { false }
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
version=5.5.0-SNAPSHOT
|
||||
spring-security.version=5.5.0-SNAPSHOT
|
||||
version=6.0.0-SNAPSHOT
|
||||
spring-security.version=6.0.0-SNAPSHOT
|
||||
|
@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
@ -20,8 +20,8 @@ import org.junit.jupiter.api.Test;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.rsocket.context.LocalRSocketServerPort;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.rsocket.server.LocalRSocketServerPort;
|
||||
import org.springframework.messaging.rsocket.RSocketRequester;
|
||||
import org.springframework.security.rsocket.metadata.SimpleAuthenticationEncoder;
|
||||
import org.springframework.security.rsocket.metadata.UsernamePasswordMetadata;
|
||||
|
@ -1,12 +1,13 @@
|
||||
plugins {
|
||||
id 'org.springframework.boot' version '2.5.0'
|
||||
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
|
||||
id "nebula.integtest" version "7.0.9"
|
||||
id 'org.springframework.boot' version '3.0.0-SNAPSHOT'
|
||||
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
|
||||
id "nebula.integtest" version "8.2.0"
|
||||
id 'java'
|
||||
}
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
maven { url "https://repo.spring.io/milestone" }
|
||||
maven { url "https://repo.spring.io/snapshot" }
|
||||
}
|
||||
|
||||
@ -21,4 +22,5 @@ dependencies {
|
||||
|
||||
tasks.withType(Test).configureEach {
|
||||
useJUnitPlatform()
|
||||
outputs.upToDateWhen { false }
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
version=5.5.0-SNAPSHOT
|
||||
spring-security.version=5.5.0-SNAPSHOT
|
||||
version=6.0.0-SNAPSHOT
|
||||
spring-security.version=6.0.0-SNAPSHOT
|
||||
|
@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
@ -28,7 +28,7 @@ import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
* @since 5.0
|
||||
*/
|
||||
@SpringBootTest
|
||||
@AutoConfigureWebTestClient
|
||||
@AutoConfigureWebTestClient(timeout = "36000")
|
||||
public class HelloTests {
|
||||
|
||||
@Autowired
|
||||
|
@ -1,12 +1,13 @@
|
||||
plugins {
|
||||
id 'org.springframework.boot' version '2.5.0'
|
||||
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
|
||||
id "nebula.integtest" version "7.0.9"
|
||||
id 'org.springframework.boot' version '3.0.0-SNAPSHOT'
|
||||
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
|
||||
id "nebula.integtest" version "8.2.0"
|
||||
id 'java'
|
||||
}
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
maven { url "https://repo.spring.io/milestone" }
|
||||
maven { url "https://repo.spring.io/snapshot" }
|
||||
}
|
||||
|
||||
@ -19,4 +20,5 @@ dependencies {
|
||||
|
||||
tasks.withType(Test).configureEach {
|
||||
useJUnitPlatform()
|
||||
outputs.upToDateWhen { false }
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
version=5.5.0-SNAPSHOT
|
||||
spring-security.version=5.5.0-SNAPSHOT
|
||||
version=6.0.0-SNAPSHOT
|
||||
spring-security.version=6.0.0-SNAPSHOT
|
||||
|
@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
@ -27,7 +27,7 @@ import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
* @since 5.0
|
||||
*/
|
||||
@SpringBootTest
|
||||
@AutoConfigureWebTestClient
|
||||
@AutoConfigureWebTestClient(timeout = "36000")
|
||||
public class HelloTests {
|
||||
|
||||
@Autowired
|
||||
|
@ -1,12 +1,13 @@
|
||||
plugins {
|
||||
id 'org.springframework.boot' version '2.5.0'
|
||||
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
|
||||
id "nebula.integtest" version "7.0.9"
|
||||
id 'org.springframework.boot' version '2.6.4'
|
||||
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
|
||||
id "nebula.integtest" version "8.2.0"
|
||||
id 'java'
|
||||
}
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
maven { url "https://repo.spring.io/milestone" }
|
||||
maven { url "https://repo.spring.io/snapshot" }
|
||||
}
|
||||
|
||||
@ -25,4 +26,5 @@ dependencies {
|
||||
|
||||
tasks.withType(Test).configureEach {
|
||||
useJUnitPlatform()
|
||||
outputs.upToDateWhen { false }
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
version=5.5.0-SNAPSHOT
|
||||
spring-security.version=5.5.0-SNAPSHOT
|
||||
version=5.7.0-SNAPSHOT
|
||||
spring-security.version=5.7.0-SNAPSHOT
|
||||
|
@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
@ -70,8 +70,10 @@ public class LoginPage {
|
||||
|
||||
private WebDriver driver;
|
||||
|
||||
@FindBy(id = "username")
|
||||
private WebElement username;
|
||||
|
||||
@FindBy(id = "password")
|
||||
private WebElement password;
|
||||
|
||||
@FindBy(css = "button[type=submit]")
|
||||
|
@ -53,7 +53,7 @@ public class WebfluxFormSecurityConfiguration {
|
||||
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
|
||||
// @formatter:off
|
||||
http
|
||||
.authorizeExchange((exchanges) -> exchanges
|
||||
.authorizeExchange((authorize) -> authorize
|
||||
.pathMatchers("/login").permitAll()
|
||||
.anyExchange().authenticated()
|
||||
)
|
||||
|
@ -1,12 +1,13 @@
|
||||
plugins {
|
||||
id 'org.springframework.boot' version '2.5.0'
|
||||
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
|
||||
id "nebula.integtest" version "7.0.9"
|
||||
id 'org.springframework.boot' version '3.0.0-SNAPSHOT'
|
||||
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
|
||||
id "nebula.integtest" version "8.2.0"
|
||||
id 'java'
|
||||
}
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
maven { url "https://repo.spring.io/milestone" }
|
||||
maven { url "https://repo.spring.io/snapshot" }
|
||||
}
|
||||
|
||||
@ -21,4 +22,5 @@ dependencies {
|
||||
|
||||
tasks.withType(Test).configureEach {
|
||||
useJUnitPlatform()
|
||||
outputs.upToDateWhen { false }
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
version=5.5.0-SNAPSHOT
|
||||
spring-security.version=5.5.0-SNAPSHOT
|
||||
version=6.0.0-SNAPSHOT
|
||||
spring-security.version=6.0.0-SNAPSHOT
|
||||
|
@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
@ -31,7 +31,7 @@ import org.junit.jupiter.api.Test;
|
||||
import reactor.netty.http.client.HttpClient;
|
||||
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.web.server.LocalServerPort;
|
||||
import org.springframework.boot.test.web.server.LocalServerPort;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.http.client.reactive.ClientHttpConnector;
|
||||
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
|
||||
|
@ -53,7 +53,7 @@ public class WebfluxX509Application {
|
||||
// @formatter:off
|
||||
http
|
||||
.x509(withDefaults())
|
||||
.authorizeExchange((exchanges) -> exchanges
|
||||
.authorizeExchange((authorize) -> authorize
|
||||
.anyExchange().authenticated()
|
||||
);
|
||||
// @formatter:on
|
||||
|
@ -1,12 +1,13 @@
|
||||
plugins {
|
||||
id 'org.springframework.boot' version '2.5.0'
|
||||
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
|
||||
id "nebula.integtest" version "7.0.9"
|
||||
id 'org.springframework.boot' version '3.0.0-SNAPSHOT'
|
||||
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
|
||||
id "nebula.integtest" version "8.2.0"
|
||||
id 'java'
|
||||
}
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
maven { url "https://repo.spring.io/milestone" }
|
||||
maven { url "https://repo.spring.io/snapshot" }
|
||||
}
|
||||
|
||||
@ -23,4 +24,5 @@ dependencies {
|
||||
|
||||
tasks.withType(Test).configureEach {
|
||||
useJUnitPlatform()
|
||||
outputs.upToDateWhen { false }
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
version=5.5.0-SNAPSHOT
|
||||
spring-security.version=5.5.0-SNAPSHOT
|
||||
version=6.0.0-SNAPSHOT
|
||||
spring-security.version=6.0.0-SNAPSHOT
|
||||
|
@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
@ -24,7 +24,7 @@ import org.openqa.selenium.WebDriver;
|
||||
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
|
||||
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.web.server.LocalServerPort;
|
||||
import org.springframework.boot.test.web.server.LocalServerPort;
|
||||
|
||||
/**
|
||||
* Integration tests.
|
||||
|
@ -51,8 +51,10 @@ public class LoginPage {
|
||||
|
||||
private WebDriver webDriver;
|
||||
|
||||
@FindBy(id = "username")
|
||||
private WebElement username;
|
||||
|
||||
@FindBy(id = "password")
|
||||
private WebElement password;
|
||||
|
||||
@FindBy(css = "button[type=submit]")
|
||||
|
@ -17,6 +17,7 @@
|
||||
package example;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
|
||||
import org.springframework.security.config.web.server.ServerHttpSecurity;
|
||||
import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;
|
||||
@ -32,6 +33,7 @@ import static org.springframework.security.config.Customizer.withDefaults;
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
@Configuration
|
||||
@EnableWebFluxSecurity
|
||||
public class SecurityConfiguration {
|
||||
|
||||
@ -39,7 +41,7 @@ public class SecurityConfiguration {
|
||||
SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http) {
|
||||
// @formatter:off
|
||||
http
|
||||
.authorizeExchange((exchanges) -> exchanges
|
||||
.authorizeExchange((authorize) -> authorize
|
||||
.anyExchange().authenticated()
|
||||
)
|
||||
.formLogin(withDefaults());
|
||||
|
@ -28,7 +28,7 @@ import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
* @since 5.0
|
||||
*/
|
||||
@SpringBootTest
|
||||
@AutoConfigureWebTestClient
|
||||
@AutoConfigureWebTestClient(timeout = "36000")
|
||||
public class HelloSecurityTests {
|
||||
|
||||
@Autowired
|
||||
|
@ -1,12 +1,13 @@
|
||||
plugins {
|
||||
id 'org.springframework.boot' version '2.5.0'
|
||||
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
|
||||
id "nebula.integtest" version "7.0.9"
|
||||
id 'org.springframework.boot' version '3.0.0-SNAPSHOT'
|
||||
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
|
||||
id "nebula.integtest" version "8.2.0"
|
||||
id 'java'
|
||||
}
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
maven { url "https://repo.spring.io/milestone" }
|
||||
maven { url "https://repo.spring.io/snapshot" }
|
||||
}
|
||||
|
||||
@ -21,4 +22,5 @@ dependencies {
|
||||
|
||||
tasks.withType(Test).configureEach {
|
||||
useJUnitPlatform()
|
||||
outputs.upToDateWhen { false }
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
version=5.5.0-SNAPSHOT
|
||||
spring-security.version=5.5.0-SNAPSHOT
|
||||
version=6.0.0-SNAPSHOT
|
||||
spring-security.version=6.0.0-SNAPSHOT
|
||||
|
@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
@ -28,7 +28,7 @@ import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
* @since 5.0
|
||||
*/
|
||||
@SpringBootTest
|
||||
@AutoConfigureWebTestClient
|
||||
@AutoConfigureWebTestClient(timeout = "36000")
|
||||
public class HelloSecurityTests {
|
||||
|
||||
@Autowired
|
||||
|
@ -1,12 +1,13 @@
|
||||
plugins {
|
||||
id 'org.springframework.boot' version '2.5.0'
|
||||
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
|
||||
id "nebula.integtest" version "7.0.9"
|
||||
id 'org.springframework.boot' version '3.0.0-SNAPSHOT'
|
||||
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
|
||||
id "nebula.integtest" version "8.2.0"
|
||||
id 'java'
|
||||
}
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
maven { url "https://repo.spring.io/milestone" }
|
||||
maven { url "https://repo.spring.io/snapshot" }
|
||||
}
|
||||
|
||||
@ -19,4 +20,5 @@ dependencies {
|
||||
|
||||
tasks.withType(Test).configureEach {
|
||||
useJUnitPlatform()
|
||||
outputs.upToDateWhen { false }
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
version=5.5.0-SNAPSHOT
|
||||
spring-security.version=5.5.0-SNAPSHOT
|
||||
version=6.0.0-SNAPSHOT
|
||||
spring-security.version=6.0.0-SNAPSHOT
|
||||
|
@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
@ -27,7 +27,7 @@ import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
* @since 5.0
|
||||
*/
|
||||
@SpringBootTest
|
||||
@AutoConfigureWebTestClient
|
||||
@AutoConfigureWebTestClient(timeout = "36000")
|
||||
public class HelloTests {
|
||||
|
||||
@Autowired
|
||||
|
@ -1,12 +1,13 @@
|
||||
plugins {
|
||||
id 'org.springframework.boot' version '2.5.0'
|
||||
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
|
||||
id "nebula.integtest" version "7.0.9"
|
||||
id 'org.springframework.boot' version '3.0.0-SNAPSHOT'
|
||||
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
|
||||
id "nebula.integtest" version "8.2.0"
|
||||
id 'java'
|
||||
}
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
maven { url "https://repo.spring.io/milestone" }
|
||||
maven { url "https://repo.spring.io/snapshot" }
|
||||
}
|
||||
|
||||
@ -21,4 +22,5 @@ dependencies {
|
||||
|
||||
tasks.withType(Test).configureEach {
|
||||
useJUnitPlatform()
|
||||
outputs.upToDateWhen { false }
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
version=5.5.0-SNAPSHOT
|
||||
spring-security.version=5.5.0-SNAPSHOT
|
||||
version=6.0.0-SNAPSHOT
|
||||
spring-security.version=6.0.0-SNAPSHOT
|
||||
|
@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
@ -45,7 +45,7 @@ public class SecurityConfiguration {
|
||||
http
|
||||
// Demonstrate that method security works
|
||||
// Best practice to use both for defense in depth
|
||||
.authorizeExchange((exchanges) -> exchanges
|
||||
.authorizeExchange((authorize) -> authorize
|
||||
.anyExchange().permitAll()
|
||||
)
|
||||
.httpBasic(withDefaults());
|
||||
|
@ -28,7 +28,7 @@ import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
* @since 5.0
|
||||
*/
|
||||
@SpringBootTest
|
||||
@AutoConfigureWebTestClient
|
||||
@AutoConfigureWebTestClient(timeout = "36000")
|
||||
public class HelloMethodApplicationTests {
|
||||
|
||||
@Autowired
|
||||
|
@ -1,18 +1,105 @@
|
||||
NOTE: Spring Security Reactive OAuth only supports authentication using a user info endpoint.
|
||||
Support for JWT validation will be added in https://github.com/spring-projects/spring-security/issues/5330[gh-5330].
|
||||
|
||||
= OAuth 2.0 Login Sample
|
||||
|
||||
This guide provides instructions on setting up the sample application with OAuth 2.0 Login using an OAuth 2.0 Provider or OpenID Connect 1.0 Provider.
|
||||
The sample application uses Spring Boot 2.0.0.M6 and the `spring-security-oauth2-client` module which is new in Spring Security 5.0.
|
||||
The sample application uses Spring Boot 2.5 and the `spring-security-oauth2-client` module which is new in Spring Security 5.0.
|
||||
|
||||
The following sections provide detailed steps for setting up OAuth 2.0 Login for these Providers:
|
||||
|
||||
* <<spring-login, Spring Authorization Server>>
|
||||
* <<google-login, Google>>
|
||||
* <<github-login, GitHub>>
|
||||
* <<facebook-login, Facebook>>
|
||||
* <<okta-login, Okta>>
|
||||
|
||||
[[spring-login]]
|
||||
== Login with Spring Authorization Server
|
||||
|
||||
This section shows how to configure the sample application using Spring Authorization Server as the Authentication Provider and covers the following topics:
|
||||
|
||||
* <<spring-initial-setup,Initial setup>>
|
||||
* <<spring-redirect-uri,Setting the redirect URI>>
|
||||
* <<spring-application-config,Configure application.yml>>
|
||||
* <<spring-boot-application,Boot up the application>>
|
||||
|
||||
[[spring-initial-setup]]
|
||||
=== Initial setup
|
||||
|
||||
The sample application is pre-configured to work out of the box with Spring Authorization Server, which runs locally on port `9000`. See the https://github.com/spring-projects/spring-security-samples/tree/main/servlet/spring-boot/java/oauth2/authorization-server[authorization-server sample] to run the authorization server used in this section.
|
||||
|
||||
NOTE: https://github.com/spring-projects-external/spring-authorization-server[Spring Authorization Server] supports the https://openid.net/connect/[OpenID Connect 1.0] specification.
|
||||
|
||||
[[spring-redirect-uri]]
|
||||
=== Setting the redirect URI
|
||||
|
||||
The redirect URI is the path in the application that the end-user's user-agent is redirected back to after they have authenticated with Spring Authorization Server
|
||||
and have granted access to the OAuth Client on the Consent page.
|
||||
|
||||
The default redirect URI is `http://127.0.0.1:8080/login/oauth2/code/login-client`. No special setup is required to use the sample locally.
|
||||
|
||||
TIP: The default redirect URI template is `{baseUrl}/login/oauth2/code/{registrationId}`.
|
||||
The *_registrationId_* is a unique identifier for the `ClientRegistration`.
|
||||
|
||||
IMPORTANT: If the application is running behind a proxy server, it is recommended to check https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#appendix-proxy-server[Proxy Server Configuration] to ensure the application is correctly configured.
|
||||
Also, see the supported https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#oauth2Client-auth-code-redirect-uri[`URI` template variables] for `redirect-uri`.
|
||||
|
||||
[[spring-application-config]]
|
||||
=== Configure application.yml
|
||||
|
||||
If you wish to customize the OAuth Client to work with a non-local deployment of Spring Authorization Server, you need to configure the application to use the OAuth Client for the _authentication flow_. To do so:
|
||||
|
||||
. Go to `application.yml` and set the following configuration:
|
||||
+
|
||||
[source,yaml]
|
||||
----
|
||||
spring:
|
||||
security:
|
||||
oauth2:
|
||||
client:
|
||||
registration: <1>
|
||||
login-client: <2>
|
||||
provider: spring <3>
|
||||
client-id: login-client
|
||||
client-secret: openid-connect
|
||||
client-authentication-method: client_secret_basic
|
||||
authorization-grant-type: authorization_code
|
||||
redirect-uri: http://127.0.0.1:8080/login/oauth2/code/login-client
|
||||
scope: openid,profile <4>
|
||||
client-name: Spring
|
||||
provider:<5>
|
||||
spring:
|
||||
authorization-uri: http://localhost:9000/oauth2/authorize
|
||||
token-uri: http://localhost:9000/oauth2/token
|
||||
jwk-set-uri: http://localhost:9000/oauth2/jwks
|
||||
issuer-uri: http://localhost:9000
|
||||
----
|
||||
+
|
||||
.OAuth Client properties
|
||||
====
|
||||
<1> `spring.security.oauth2.client.registration` is the base property prefix for OAuth Client properties.
|
||||
<2> Following the base property prefix is the ID for the `ClientRegistration`, such as login-client.
|
||||
<3> The `provider` property specifies which provider configuration is used by this `ClientRegistration`.
|
||||
<4> The `openid` scope is required by Spring Authorization Server to perform https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth[authentication using OpenID Connect 1.0].
|
||||
<5> `spring.security.oauth2.client.provider` is the base property prefix for OAuth Provider properties.
|
||||
====
|
||||
|
||||
. Replace the values in the `client-id` and `client-secret` property with the OAuth 2.0 credentials for your Spring Authorization Server. As well, replace `http://localhost:9000` in `authorization-uri`, `token-uri` and `jwk-set-uri` with the actual domain of your authorization server.
|
||||
|
||||
[[spring-boot-application]]
|
||||
=== Boot up the application
|
||||
|
||||
Launch the Spring Boot 2.0 sample and go to `http://127.0.0.1:8080`.
|
||||
You are then redirected to the default _auto-generated_ login page, which displays a link for Spring.
|
||||
|
||||
Click on the Spring link, and you are then redirected to the Spring Authorization Server for authentication.
|
||||
|
||||
After authenticating with your credentials (`user` and `password` by default), the next page presented to you is the Consent screen.
|
||||
The Consent screen asks you to either allow or deny access to the OAuth Client. Select "profile" and
|
||||
click *Submit Consent* to authorize the OAuth Client to access your basic profile information.
|
||||
|
||||
At this point, the OAuth Client retrieves your basic profile information via the https://openid.net/specs/openid-connect-core-1_0.html#CodeIDToken[ID Token] and establishes an authenticated session.
|
||||
|
||||
NOTE: Spring Authorization Server does not currently support the https://openid.net/specs/openid-connect-core-1_0.html#UserInfo[UserInfo Endpoint], which is optional in OpenID Connect 1.0. See https://github.com/spring-projects-experimental/spring-authorization-server/issues/176[#176] fo more information.
|
||||
|
||||
[[google-login]]
|
||||
== Login with Google
|
||||
|
||||
@ -41,7 +128,7 @@ After completing the "Obtain OAuth 2.0 credentials" instructions, you should hav
|
||||
The redirect URI is the path in the application that the end-user's user-agent is redirected back to after they have authenticated with Google
|
||||
and have granted access to the OAuth Client _(created in the previous step)_ on the Consent page.
|
||||
|
||||
In the "Set a redirect URI" sub-section, ensure that the *Authorized redirect URIs* field is set to `http://localhost:8080/login/oauth2/code/google`.
|
||||
In the "Set a redirect URI" sub-section, ensure that the *Authorized redirect URIs* field is set to `http://127.0.0.1:8080/login/oauth2/code/google`.
|
||||
|
||||
TIP: The default redirect URI template is `{baseUrl}/login/oauth2/code/{registrationId}`.
|
||||
The *_registrationId_* is a unique identifier for the `ClientRegistration`.
|
||||
@ -79,7 +166,7 @@ spring:
|
||||
[[google-boot-application]]
|
||||
=== Boot up the application
|
||||
|
||||
Launch the Spring Boot 2.0 sample and go to `http://localhost:8080`.
|
||||
Launch the Spring Boot 2.0 sample and go to `http://127.0.0.1:8080`.
|
||||
You are then redirected to the default _auto-generated_ login page, which displays a link for Google.
|
||||
|
||||
Click on the Google link, and you are then redirected to Google for authentication.
|
||||
@ -105,7 +192,7 @@ This section shows how to configure the sample application using GitHub as the A
|
||||
|
||||
To use GitHub's OAuth 2.0 authentication system for login, you must https://github.com/settings/applications/new[Register a new OAuth application].
|
||||
|
||||
When registering the OAuth application, ensure the *Authorization callback URL* is set to `http://localhost:8080/login/oauth2/code/github`.
|
||||
When registering the OAuth application, ensure the *Authorization callback URL* is set to `http://127.0.0.1:8080/login/oauth2/code/github`.
|
||||
|
||||
The Authorization callback URL (redirect URI) is the path in the application that the end-user's user-agent is redirected back to after they have authenticated with GitHub
|
||||
and have granted access to the OAuth application on the _Authorize application_ page.
|
||||
@ -146,7 +233,7 @@ spring:
|
||||
[[github-boot-application]]
|
||||
=== Boot up the application
|
||||
|
||||
Launch the Spring Boot 2.0 sample and go to `http://localhost:8080`.
|
||||
Launch the Spring Boot 2.0 sample and go to `http://127.0.0.1:8080`.
|
||||
You are then redirected to the default _auto-generated_ login page, which displays a link for GitHub.
|
||||
|
||||
Click on the GitHub link, and you are then redirected to GitHub for authentication.
|
||||
@ -183,7 +270,7 @@ NOTE: The selection for the _Category_ field is not relevant but it's a required
|
||||
The next page presented is "Product Setup". Click the "Get Started" button for the *Facebook Login* product.
|
||||
In the left sidebar, under _Products -> Facebook Login_, select _Settings_.
|
||||
|
||||
For the field *Valid OAuth redirect URIs*, enter `http://localhost:8080/login/oauth2/code/facebook` then click _Save Changes_.
|
||||
For the field *Valid OAuth redirect URIs*, enter `http://127.0.0.1:8080/login/oauth2/code/facebook` then click _Save Changes_.
|
||||
|
||||
The OAuth redirect URI is the path in the application that the end-user's user-agent is redirected back to after they have authenticated with Facebook
|
||||
and have granted access to the application on the _Authorize application_ page.
|
||||
@ -224,7 +311,7 @@ spring:
|
||||
[[facebook-boot-application]]
|
||||
=== Boot up the application
|
||||
|
||||
Launch the Spring Boot 2.0 sample and go to `http://localhost:8080`.
|
||||
Launch the Spring Boot 2.0 sample and go to `http://127.0.0.1:8080`.
|
||||
You are then redirected to the default _auto-generated_ login page, which displays a link for Facebook.
|
||||
|
||||
Click on the Facebook link, and you are then redirected to Facebook for authentication.
|
||||
@ -259,7 +346,7 @@ From the "Add Application" page, select the "Create New App" button and enter th
|
||||
|
||||
Select the _Create_ button.
|
||||
On the "General Settings" page, enter the Application Name (for example, "Spring Security Okta Login") and then select the _Next_ button.
|
||||
On the "Configure OpenID Connect" page, enter `http://localhost:8080/login/oauth2/code/okta` for the field *Redirect URIs* and then select _Finish_.
|
||||
On the "Configure OpenID Connect" page, enter `http://127.0.0.1:8080/login/oauth2/code/okta` for the field *Redirect URIs* and then select _Finish_.
|
||||
|
||||
The redirect URI is the path in the application that the end-user's user-agent is redirected back to after they have authenticated with Okta
|
||||
and have granted access to the application on the _Authorize application_ page.
|
||||
@ -315,7 +402,7 @@ As well, replace `https://your-subdomain.oktapreview.com` in `authorization-uri`
|
||||
[[okta-boot-application]]
|
||||
=== Boot up the application
|
||||
|
||||
Launch the Spring Boot 2.0 sample and go to `http://localhost:8080`.
|
||||
Launch the Spring Boot 2.0 sample and go to `http://127.0.0.1:8080`.
|
||||
You are then redirected to the default _auto-generated_ login page, which displays a link for Okta.
|
||||
|
||||
Click on the Okta link, and you are then redirected to Okta for authentication.
|
||||
|
@ -1,12 +1,13 @@
|
||||
plugins {
|
||||
id 'org.springframework.boot' version '2.5.0'
|
||||
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
|
||||
id "nebula.integtest" version "7.0.9"
|
||||
id 'org.springframework.boot' version '3.0.0-SNAPSHOT'
|
||||
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
|
||||
id "nebula.integtest" version "8.2.0"
|
||||
id 'java'
|
||||
}
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
maven { url "https://repo.spring.io/milestone" }
|
||||
maven { url "https://repo.spring.io/snapshot" }
|
||||
}
|
||||
|
||||
@ -14,7 +15,7 @@ dependencies {
|
||||
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-webflux'
|
||||
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5'
|
||||
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6'
|
||||
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||
testImplementation 'org.springframework.security:spring-security-test'
|
||||
@ -24,4 +25,5 @@ dependencies {
|
||||
|
||||
tasks.withType(Test).configureEach {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
outputs.upToDateWhen { false }
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
version=5.5.0-SNAPSHOT
|
||||
spring-security.version=5.5.0-SNAPSHOT
|
||||
version=6.0.0-SNAPSHOT
|
||||
spring-security.version=6.0.0-SNAPSHOT
|
||||
|
@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
@ -36,7 +36,7 @@ import static org.springframework.security.test.web.reactive.server.SecurityMock
|
||||
* @author Rob Winch
|
||||
*/
|
||||
@SpringBootTest
|
||||
@AutoConfigureWebTestClient
|
||||
@AutoConfigureWebTestClient(timeout = "36000")
|
||||
public class OAuth2LoginApplicationTests {
|
||||
|
||||
@Autowired
|
||||
|
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package example;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebFilter;
|
||||
import org.springframework.web.server.WebFilterChain;
|
||||
import org.springframework.web.util.UriComponents;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
/**
|
||||
* This filter ensures that the loopback IP <code>127.0.0.1</code> is used to access the
|
||||
* application so that the sample works correctly, due to the fact that redirect URIs with
|
||||
* "localhost" are rejected by the Spring Authorization Server, because the OAuth 2.1
|
||||
* draft specification states:
|
||||
*
|
||||
* <pre>
|
||||
* While redirect URIs using localhost (i.e.,
|
||||
* "http://localhost:{port}/{path}") function similarly to loopback IP
|
||||
* redirects described in Section 10.3.3, the use of "localhost" is NOT
|
||||
* RECOMMENDED.
|
||||
* </pre>
|
||||
*
|
||||
* @author Steve Riesenberg
|
||||
* @see <a href=
|
||||
* "https://tools.ietf.org/html/draft-ietf-oauth-v2-1-01#section-9.7.1">Loopback Redirect
|
||||
* Considerations in Native Apps</a>
|
||||
*/
|
||||
@Component
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
public class LoopbackIpRedirectWebFilter implements WebFilter {
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
|
||||
String host = exchange.getRequest().getURI().getHost();
|
||||
if (host != null && host.equals("localhost")) {
|
||||
UriComponents uri = UriComponentsBuilder.fromHttpRequest(exchange.getRequest()).host("127.0.0.1").build();
|
||||
exchange.getResponse().setStatusCode(HttpStatus.PERMANENT_REDIRECT);
|
||||
exchange.getResponse().getHeaders().setLocation(uri.toUri());
|
||||
return Mono.empty();
|
||||
}
|
||||
return chain.filter(exchange);
|
||||
}
|
||||
|
||||
}
|
@ -15,6 +15,15 @@ spring:
|
||||
oauth2:
|
||||
client:
|
||||
registration:
|
||||
login-client:
|
||||
provider: spring
|
||||
client-id: login-client
|
||||
client-secret: openid-connect
|
||||
client-authentication-method: client_secret_basic
|
||||
authorization-grant-type: authorization_code
|
||||
redirect-uri: http://127.0.0.1:8080/login/oauth2/code/login-client
|
||||
scope: openid,profile
|
||||
client-name: Spring
|
||||
google:
|
||||
client-id: your-app-client-id
|
||||
client-secret: your-app-client-secret
|
||||
@ -28,6 +37,10 @@ spring:
|
||||
client-id: your-app-client-id
|
||||
client-secret: your-app-client-secret
|
||||
provider:
|
||||
spring:
|
||||
authorization-uri: http://localhost:9000/oauth2/authorize
|
||||
token-uri: http://localhost:9000/oauth2/token
|
||||
jwk-set-uri: http://localhost:9000/oauth2/jwks
|
||||
okta:
|
||||
authorization-uri: https://your-subdomain.oktapreview.com/oauth2/v1/authorize
|
||||
token-uri: https://your-subdomain.oktapreview.com/oauth2/v1/token
|
||||
|
@ -1,7 +1,7 @@
|
||||
= OAuth 2.0 Resource Server Sample
|
||||
|
||||
This sample demonstrates integrating Resource Server with a mock Authorization Server, though it can be modified to integrate
|
||||
with your favorite Authorization Server.
|
||||
This sample demonstrates integrating Resource Server with the Spring Authorization Server, though it can be modified to integrate
|
||||
with a mock server or your favorite Authorization Server.
|
||||
|
||||
With it, you can run the integration tests or run the application as a stand-alone service to explore how you can
|
||||
secure your own service with OAuth 2.0 Bearer Tokens using Spring Security.
|
||||
@ -18,7 +18,7 @@ Or import the project into your IDE and run `ServerOAuth2ResourceServerApplicati
|
||||
|
||||
=== What is it doing?
|
||||
|
||||
By default, the tests are pointing at a mock Authorization Server instance.
|
||||
By default, the tests are pointing at a mock Authorization Server instance via the `test` profile.
|
||||
|
||||
The tests are configured with a set of hard-coded tokens originally obtained from the mock Authorization Server,
|
||||
and each makes a query to the Resource Server with their corresponding token.
|
||||
@ -31,7 +31,17 @@ Hello, subject!
|
||||
|
||||
where "subject" is the value of the `sub` field in the JWT returned by the Authorization Server.
|
||||
|
||||
== 2. Running the app
|
||||
== 2. Running the app with Spring Authorization Server
|
||||
|
||||
Before running this application with the default configuration, you will need to start up an Authorization Server, such as the https://github.com/spring-projects/spring-security-samples/tree/main/servlet/spring-boot/java/oauth2/authorization-server[authorization-server sample] in this project which is pre-configured to work with this Resource Server sample out of the box.
|
||||
|
||||
To run the Authorization Server as a stand-alone application, navigate to the `servlet/spring-boot/java/oauth2/authorization-server` and do:
|
||||
|
||||
```bash
|
||||
./gradlew bootRun
|
||||
```
|
||||
|
||||
Or import the project into your IDE and run `OAuth2AuthorizationServerApplication` from there. Next, you can run this Resource Server.
|
||||
|
||||
To run as a stand-alone application, do:
|
||||
|
||||
@ -41,6 +51,89 @@ To run as a stand-alone application, do:
|
||||
|
||||
Or import the project into your IDE and run `ServerOAuth2ResourceServerApplication` from there.
|
||||
|
||||
Once it is up and running, you can issue the following request:
|
||||
|
||||
```bash
|
||||
curl -X POST messaging-client:secret@localhost:9000/oauth2/token -d "grant_type=client_credentials" -d "scope=message:read"
|
||||
```
|
||||
|
||||
This returns something like the following:
|
||||
|
||||
```json
|
||||
{
|
||||
"access_token": "eyJraWQiOiI4YWY4Zjc2Zi0zMTdkLTQxZmYtYWY5Yi1hZjg5NDg4ODM5YzciLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJtZXNzYWdpbmctY2xpZW50IiwiYXVkIjoibWVzc2FnaW5nLWNsaWVudCIsIm5iZiI6MTYyNzMzNDQ1MCwic2NvcGUiOlsibWVzc2FnZTpyZWFkIl0sImlzcyI6Imh0dHA6XC9cL2xvY2FsaG9zdDo5MDAwIiwiZXhwIjoxNjI3MzM0NzUwLCJpYXQiOjE2MjczMzQ0NTAsImp0aSI6IjBiYjYwZjhkLWIzNjItNDk0MC05MGRmLWZhZDg4N2Q1Yzg1ZSJ9.O8dI67B_feRjOn6pJi5ctPJmUJCNpV77SC4OiWqmpa5UHvf4Ud6L6EFe9LKuPIRrEWi8rMdCdMBOPKQMXvxLoI3LMUPf7Yj973uvZN0E988MsKwhGwxyaa_Wam8wFlk8aQlN8SbW3cKdeH-nKloNMdwjfspovefX521mxouaMjmyXdIFrM5WZ15GZK69NIniACSatE-pc9TAjKYBDbC65jVt_zHEvDQbEkZulF2bjrGOZC8C3IbJWnlKgkcshrY44TtrGPyCp2gIS0TSUUsG00iSBBC8E8zPU-YdfaP8gB9_FwUwK9zfy_hU2Ykf2aU3eulpGDVLn2rCwFeK86Rw1w",
|
||||
"expires_in": 299,
|
||||
"scope": "message:read",
|
||||
"token_type": "Bearer"
|
||||
}
|
||||
```
|
||||
|
||||
Then, export the access token from the response:
|
||||
|
||||
```bash
|
||||
export TOKEN=...
|
||||
```
|
||||
|
||||
Then issue the following request:
|
||||
|
||||
```bash
|
||||
curl -H "Authorization: Bearer $TOKEN" localhost:8080
|
||||
```
|
||||
|
||||
Which will respond with the phrase:
|
||||
|
||||
```
|
||||
Hello, messaging-client!
|
||||
```
|
||||
|
||||
where `messaging-client` is the value of the `sub` field in the JWT returned by the Authorization Server.
|
||||
|
||||
Or this to make a GET request to /message:
|
||||
|
||||
```bash
|
||||
curl -H "Authorization: Bearer $TOKEN" localhost:8080/message
|
||||
```
|
||||
|
||||
Will respond with:
|
||||
|
||||
```bash
|
||||
secret message
|
||||
```
|
||||
|
||||
In order to make a POST request to /message, you can use the following request:
|
||||
|
||||
```bash
|
||||
curl -X POST messaging-client:secret@localhost:9000/oauth2/token -d "grant_type=client_credentials" -d "scope=message:write"
|
||||
```
|
||||
|
||||
Then, export the access token from the response:
|
||||
|
||||
```bash
|
||||
export TOKEN=...
|
||||
```
|
||||
|
||||
Then issue the following request:
|
||||
|
||||
```bash
|
||||
curl -H "Authorization: Bearer $TOKEN" -d "my message" localhost:8080/message
|
||||
```
|
||||
|
||||
Which will respond with:
|
||||
|
||||
```bash
|
||||
Message was created. Content: my message
|
||||
```
|
||||
|
||||
== 3. Running the app with a mock Authorization Server
|
||||
|
||||
To run as a stand-alone application with an embedded mock Authorization Server, do:
|
||||
|
||||
```bash
|
||||
./gradlew bootRun --args='--spring.profiles.active=test'
|
||||
```
|
||||
|
||||
Or import the project into your IDE and run `ServerOAuth2ResourceServerApplication` from there with the `test` profile active.
|
||||
|
||||
Once it is up, you can use the following token:
|
||||
|
||||
```bash
|
||||
@ -75,7 +168,7 @@ Will respond with:
|
||||
secret message
|
||||
```
|
||||
|
||||
== 2. Testing against other Authorization Servers
|
||||
== 4. Testing against other Authorization Servers
|
||||
|
||||
_In order to use this sample, your Authorization Server must support JWTs that either use the "scope" or "scp" attribute._
|
||||
|
||||
@ -87,7 +180,7 @@ spring:
|
||||
oauth2:
|
||||
resourceserver:
|
||||
jwt:
|
||||
jwk-set-uri: ${mockwebserver.url}/.well-known/jwks.json
|
||||
jwk-set-uri: http://localhost:9000/oauth2/jwks
|
||||
```
|
||||
|
||||
And change the property to your Authorization Server's JWK set endpoint:
|
||||
|
@ -1,12 +1,13 @@
|
||||
plugins {
|
||||
id 'org.springframework.boot' version '2.5.0'
|
||||
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
|
||||
id "nebula.integtest" version "7.0.9"
|
||||
id 'org.springframework.boot' version '3.0.0-SNAPSHOT'
|
||||
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
|
||||
id "nebula.integtest" version "8.2.0"
|
||||
id 'java'
|
||||
}
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
maven { url "https://repo.spring.io/milestone" }
|
||||
maven { url "https://repo.spring.io/snapshot" }
|
||||
}
|
||||
|
||||
@ -21,4 +22,5 @@ dependencies {
|
||||
|
||||
tasks.withType(Test).configureEach {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
outputs.upToDateWhen { false }
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
version=5.5.0-SNAPSHOT
|
||||
spring-security.version=5.5.0-SNAPSHOT
|
||||
version=6.0.0-SNAPSHOT
|
||||
spring-security.version=6.0.0-SNAPSHOT
|
||||
|
@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
@ -24,6 +24,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
@ -35,7 +36,8 @@ import static org.hamcrest.Matchers.containsString;
|
||||
* @since 5.1
|
||||
*/
|
||||
@SpringBootTest
|
||||
@AutoConfigureWebTestClient
|
||||
@AutoConfigureWebTestClient(timeout = "36000")
|
||||
@ActiveProfiles("test")
|
||||
public class ServerOAuth2ResourceServerApplicationITests {
|
||||
|
||||
Consumer<HttpHeaders> noScopesToken = (http) -> http.setBearerAuth(
|
||||
|
@ -17,6 +17,7 @@
|
||||
package example;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
|
||||
import org.springframework.security.config.web.server.ServerHttpSecurity;
|
||||
@ -30,6 +31,7 @@ import static org.springframework.security.config.Customizer.withDefaults;
|
||||
* @author Rob Winch
|
||||
* @since 5.1
|
||||
*/
|
||||
@Configuration
|
||||
@EnableWebFluxSecurity
|
||||
public class SecurityConfiguration {
|
||||
|
||||
@ -37,7 +39,7 @@ public class SecurityConfiguration {
|
||||
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
|
||||
// @formatter:off
|
||||
http
|
||||
.authorizeExchange((exchanges) -> exchanges
|
||||
.authorizeExchange((authorize) -> authorize
|
||||
.pathMatchers(HttpMethod.GET, "/message/**").hasAuthority("SCOPE_message:read")
|
||||
.pathMatchers(HttpMethod.POST, "/message/**").hasAuthority("SCOPE_message:write")
|
||||
.anyExchange().authenticated()
|
||||
|
@ -0,0 +1,6 @@
|
||||
spring:
|
||||
security:
|
||||
oauth2:
|
||||
resourceserver:
|
||||
jwt:
|
||||
jwk-set-uri: ${mockwebserver.url}/.well-known/jwks.json
|
@ -3,4 +3,4 @@ spring:
|
||||
oauth2:
|
||||
resourceserver:
|
||||
jwt:
|
||||
jwk-set-uri: ${mockwebserver.url}/.well-known/jwks.json
|
||||
jwk-set-uri: http://localhost:9000/oauth2/jwks
|
||||
|
@ -1,12 +1,13 @@
|
||||
plugins {
|
||||
id 'org.springframework.boot' version '2.5.0'
|
||||
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
|
||||
id "nebula.integtest" version "7.0.9"
|
||||
id 'org.springframework.boot' version '3.0.0-SNAPSHOT'
|
||||
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
|
||||
id "nebula.integtest" version "8.2.0"
|
||||
id 'java'
|
||||
}
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
maven { url "https://repo.spring.io/milestone" }
|
||||
maven { url "https://repo.spring.io/snapshot" }
|
||||
}
|
||||
|
||||
@ -14,7 +15,7 @@ dependencies {
|
||||
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
|
||||
implementation 'org.springframework:spring-webflux'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
|
||||
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5'
|
||||
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6'
|
||||
implementation 'io.projectreactor.netty:reactor-netty'
|
||||
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||
@ -24,4 +25,5 @@ dependencies {
|
||||
|
||||
tasks.withType(Test).configureEach {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
outputs.upToDateWhen { false }
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
version=5.5.0-SNAPSHOT
|
||||
spring-security.version=5.5.0-SNAPSHOT
|
||||
version=6.0.0-SNAPSHOT
|
||||
spring-security.version=6.0.0-SNAPSHOT
|
||||
|
@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
@ -16,6 +16,7 @@
|
||||
package example;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
|
||||
import org.springframework.security.config.web.server.ServerHttpSecurity;
|
||||
import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;
|
||||
@ -30,6 +31,7 @@ import static org.springframework.security.config.Customizer.withDefaults;
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
@Configuration
|
||||
@EnableWebFluxSecurity
|
||||
public class SecurityConfiguration {
|
||||
|
||||
@ -37,7 +39,7 @@ public class SecurityConfiguration {
|
||||
SecurityWebFilterChain configure(ServerHttpSecurity http) {
|
||||
// @formatter:off
|
||||
http
|
||||
.authorizeExchange((exchanges) -> exchanges
|
||||
.authorizeExchange((authorize) -> authorize
|
||||
.pathMatchers("/", "/public/**").permitAll()
|
||||
.anyExchange().authenticated()
|
||||
)
|
||||
|
@ -39,7 +39,7 @@ import static org.springframework.security.test.web.reactive.server.SecurityMock
|
||||
|
||||
@WebFluxTest
|
||||
@Import({ SecurityConfiguration.class, OAuth2WebClientController.class })
|
||||
@AutoConfigureWebTestClient
|
||||
@AutoConfigureWebTestClient(timeout = "36000")
|
||||
public class OAuth2WebClientControllerTests {
|
||||
|
||||
private static MockWebServer web = new MockWebServer();
|
||||
|
@ -27,7 +27,7 @@ import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
* @author Rob Winch
|
||||
*/
|
||||
@SpringBootTest
|
||||
@AutoConfigureWebTestClient
|
||||
@AutoConfigureWebTestClient(timeout = "36000")
|
||||
public class OAuth2WebClientWebFluxApplicationTests {
|
||||
|
||||
@Autowired
|
||||
|
@ -39,7 +39,7 @@ import static org.springframework.security.test.web.reactive.server.SecurityMock
|
||||
|
||||
@WebFluxTest
|
||||
@Import({ SecurityConfiguration.class, RegisteredOAuth2AuthorizedClientController.class })
|
||||
@AutoConfigureWebTestClient
|
||||
@AutoConfigureWebTestClient(timeout = "36000")
|
||||
public class RegisteredOAuth2AuthorizedClientControllerTests {
|
||||
|
||||
private static MockWebServer web = new MockWebServer();
|
||||
|
@ -1,16 +1,19 @@
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
plugins {
|
||||
id("org.springframework.boot") version "2.2.6.RELEASE"
|
||||
id("io.spring.dependency-management") version "1.0.9.RELEASE"
|
||||
kotlin("jvm") version "1.3.71"
|
||||
kotlin("plugin.spring") version "1.3.71"
|
||||
id("org.springframework.boot") version "3.0.0-SNAPSHOT"
|
||||
id("io.spring.dependency-management") version "1.0.11.RELEASE"
|
||||
kotlin("jvm") version "1.6.0"
|
||||
kotlin("plugin.spring") version "1.6.0"
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
url = uri("https://repo.spring.io/libs-snapshot")
|
||||
url = uri("https://repo.spring.io/snapshot")
|
||||
}
|
||||
maven {
|
||||
url = uri("https://repo.spring.io/milestone")
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,7 +21,7 @@ dependencies {
|
||||
implementation("org.springframework.boot:spring-boot-starter-security")
|
||||
implementation("org.springframework.boot:spring-boot-starter-thymeleaf")
|
||||
implementation("org.springframework.boot:spring-boot-starter-webflux")
|
||||
implementation("org.thymeleaf.extras:thymeleaf-extras-springsecurity5")
|
||||
implementation("org.thymeleaf.extras:thymeleaf-extras-springsecurity6")
|
||||
implementation("io.projectreactor.kotlin:reactor-kotlin-extensions")
|
||||
implementation("org.jetbrains.kotlin:kotlin-reflect")
|
||||
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
|
||||
@ -34,10 +37,10 @@ dependencies {
|
||||
tasks.withType<KotlinCompile> {
|
||||
kotlinOptions {
|
||||
freeCompilerArgs = listOf("-Xjsr305=strict")
|
||||
jvmTarget = "1.8"
|
||||
jvmTarget = "17"
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<Test> {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
spring-security.version=5.4.0.BUILD-SNAPSHOT
|
||||
spring-security.version=6.0.0-SNAPSHOT
|
||||
|
@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
@ -17,6 +17,7 @@
|
||||
package example
|
||||
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity
|
||||
import org.springframework.security.config.web.server.ServerHttpSecurity
|
||||
import org.springframework.security.config.web.server.invoke
|
||||
@ -25,6 +26,7 @@ import org.springframework.security.core.userdetails.ReactiveUserDetailsService
|
||||
import org.springframework.security.core.userdetails.User
|
||||
import org.springframework.security.web.server.SecurityWebFilterChain
|
||||
|
||||
@Configuration
|
||||
@EnableWebFluxSecurity
|
||||
class SecurityConfiguration {
|
||||
|
||||
|
@ -4,10 +4,21 @@ plugins {
|
||||
}
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
maven { url "https://repo.spring.io/milestone" }
|
||||
maven { url "https://repo.spring.io/snapshot" }
|
||||
}
|
||||
|
||||
compileJava {
|
||||
sourceCompatibility "1.8"
|
||||
targetCompatibility "1.8"
|
||||
}
|
||||
|
||||
compileTestJava {
|
||||
sourceCompatibility "1.8"
|
||||
targetCompatibility "1.8"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
aspect platform("org.springframework:spring-framework-bom:5.3.0")
|
||||
aspect platform("org.springframework.security:spring-security-bom:5.4.0-SNAPSHOT")
|
||||
@ -19,7 +30,7 @@ dependencies {
|
||||
|
||||
implementation "org.springframework.security:spring-security-config"
|
||||
|
||||
runtime "org.springframework.security:spring-security-aspects"
|
||||
runtimeOnly "org.springframework.security:spring-security-aspects"
|
||||
|
||||
testImplementation "org.assertj:assertj-core:3.18.0"
|
||||
testImplementation "org.springframework:spring-test"
|
||||
@ -31,6 +42,7 @@ dependencies {
|
||||
|
||||
tasks.withType(Test).configureEach {
|
||||
useJUnitPlatform()
|
||||
outputs.upToDateWhen { false }
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
@ -1,14 +1,15 @@
|
||||
plugins {
|
||||
id "java"
|
||||
id "nebula.integtest" version "7.0.9"
|
||||
id "org.gretty" version "3.0.3"
|
||||
id "nebula.integtest" version "8.2.0"
|
||||
id "org.gretty" version "3.0.6"
|
||||
id "war"
|
||||
}
|
||||
|
||||
apply from: "gradle/gretty.gradle"
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
maven { url "https://repo.spring.io/milestone" }
|
||||
maven { url "https://repo.spring.io/snapshot" }
|
||||
}
|
||||
|
||||
@ -29,9 +30,10 @@ dependencies {
|
||||
|
||||
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
|
||||
|
||||
integTestImplementation "org.seleniumhq.selenium:htmlunit-driver:2.44.0"
|
||||
integTestImplementation "org.seleniumhq.selenium:htmlunit-driver:3.64.0"
|
||||
}
|
||||
|
||||
tasks.withType(Test).configureEach {
|
||||
useJUnitPlatform()
|
||||
outputs.upToDateWhen { false }
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
@ -16,32 +16,31 @@
|
||||
package example;
|
||||
|
||||
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;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
public class SecurityConfiguration {
|
||||
|
||||
// @formatter:off
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
@Bean
|
||||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.authorizeRequests((authorizeRequests) ->
|
||||
authorizeRequests
|
||||
.antMatchers("/login", "/resources/**").permitAll()
|
||||
.anyRequest().authenticated()
|
||||
.authorizeHttpRequests((authorize) -> authorize
|
||||
.antMatchers("/login", "/resources/**").permitAll()
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.jee((jee) ->
|
||||
jee
|
||||
.mappableRoles("USER", "ADMIN")
|
||||
);
|
||||
.jee((jee) -> jee.mappableRoles("USER", "ADMIN"));
|
||||
// @formatter:on
|
||||
return http.build();
|
||||
}
|
||||
// @formatter:on
|
||||
|
||||
// @formatter:off
|
||||
@Bean
|
||||
|
@ -1,14 +1,15 @@
|
||||
plugins {
|
||||
id "java"
|
||||
id "nebula.integtest" version "7.0.9"
|
||||
id "org.gretty" version "3.0.3"
|
||||
id "nebula.integtest" version "8.2.0"
|
||||
id "org.gretty" version "3.0.6"
|
||||
id "war"
|
||||
}
|
||||
|
||||
apply from: "gradle/gretty.gradle"
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
maven { url "https://repo.spring.io/milestone" }
|
||||
maven { url "https://repo.spring.io/snapshot" }
|
||||
}
|
||||
|
||||
@ -29,9 +30,10 @@ dependencies {
|
||||
|
||||
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
|
||||
|
||||
integTestImplementation "org.seleniumhq.selenium:htmlunit-driver:2.44.0"
|
||||
integTestImplementation "org.seleniumhq.selenium:htmlunit-driver:3.64.0"
|
||||
}
|
||||
|
||||
tasks.withType(Test).configureEach {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
outputs.upToDateWhen { false }
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
@ -16,33 +16,34 @@
|
||||
package example;
|
||||
|
||||
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;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
|
||||
import static org.springframework.security.config.Customizer.withDefaults;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
public class SecurityConfiguration {
|
||||
|
||||
@Override
|
||||
// @formatter:off
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
@Bean
|
||||
public SecurityFilterChain securityFilterChain(HttpSecurity http, UserDetailsService users) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.authorizeRequests((requests) -> requests
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.formLogin((form) -> form
|
||||
.loginPage("/login")
|
||||
.permitAll()
|
||||
)
|
||||
.rememberMe(withDefaults());
|
||||
.authorizeRequests((authorize) -> authorize
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.formLogin((form) -> form
|
||||
.loginPage("/login")
|
||||
.permitAll()
|
||||
)
|
||||
.rememberMe((rememberMe) -> rememberMe.userDetailsService(users));
|
||||
// @formatter:on
|
||||
return http.build();
|
||||
}
|
||||
// @formatter:on
|
||||
|
||||
// @formatter:off
|
||||
@Bean
|
||||
|
@ -1,26 +1,27 @@
|
||||
plugins {
|
||||
id "java"
|
||||
id "nebula.integtest" version "7.0.9"
|
||||
id "org.gretty" version "3.0.3"
|
||||
id "nebula.integtest" version "8.2.0"
|
||||
id "org.gretty" version "4.0.0"
|
||||
id "war"
|
||||
}
|
||||
|
||||
apply from: "gradle/gretty.gradle"
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
maven { url "https://repo.spring.io/milestone" }
|
||||
maven { url "https://repo.spring.io/snapshot" }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation platform("org.springframework:spring-framework-bom:5.3.0")
|
||||
implementation platform("org.springframework.security:spring-security-bom:5.5.0-SNAPSHOT")
|
||||
implementation platform("org.springframework:spring-framework-bom:6.0.0-SNAPSHOT")
|
||||
implementation platform("org.springframework.security:spring-security-bom:6.0.0-SNAPSHOT")
|
||||
implementation platform("org.junit:junit-bom:5.7.0")
|
||||
|
||||
implementation "org.springframework.security:spring-security-config"
|
||||
implementation "org.springframework.security:spring-security-web"
|
||||
implementation "org.springframework:spring-webmvc"
|
||||
implementation "org.thymeleaf:thymeleaf-spring5:3.0.11.RELEASE"
|
||||
implementation "org.thymeleaf:thymeleaf-spring6:3.1.0.M1"
|
||||
|
||||
testImplementation "org.assertj:assertj-core:3.18.0"
|
||||
testImplementation "org.springframework:spring-test"
|
||||
@ -29,9 +30,10 @@ dependencies {
|
||||
|
||||
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
|
||||
|
||||
integTestImplementation "org.seleniumhq.selenium:htmlunit-driver:2.44.0"
|
||||
integTestImplementation "org.seleniumhq.selenium:htmlunit-driver:3.64.0"
|
||||
}
|
||||
|
||||
tasks.withType(Test).configureEach {
|
||||
useJUnitPlatform()
|
||||
outputs.upToDateWhen { false }
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
gretty {
|
||||
servletContainer = "tomcat9"
|
||||
servletContainer = "tomcat10"
|
||||
contextPath = "/"
|
||||
fileLogEnabled = false
|
||||
integrationTestTask = 'integrationTest'
|
||||
@ -38,4 +38,4 @@ project.tasks.matching { it.name == "integrationTest" }.all {
|
||||
integrationTest.systemProperty 'app.httpBaseURI', httpBaseUrl
|
||||
integrationTest.systemProperty 'app.httpsBaseURI', httpsBaseUrl
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
package example;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import jakarta.servlet.Filter;
|
||||
|
||||
import org.springframework.web.filter.HiddenHttpMethodFilter;
|
||||
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
|
||||
|
@ -16,30 +16,33 @@
|
||||
package example;
|
||||
|
||||
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;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
public class SecurityConfiguration {
|
||||
|
||||
@Override
|
||||
// @formatter:off
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
@Bean
|
||||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.authorizeRequests((requests) -> requests
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.formLogin((form) -> form
|
||||
.loginPage("/login")
|
||||
.permitAll()
|
||||
);
|
||||
.authorizeRequests((authorize) -> authorize
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.formLogin((form) -> form
|
||||
.loginPage("/login")
|
||||
.permitAll()
|
||||
);
|
||||
// @formatter:on
|
||||
return http.build();
|
||||
}
|
||||
// @formatter:on
|
||||
|
||||
// @formatter:off
|
||||
@Bean
|
||||
|
@ -16,10 +16,10 @@
|
||||
|
||||
package example;
|
||||
|
||||
import org.thymeleaf.spring5.ISpringTemplateEngine;
|
||||
import org.thymeleaf.spring5.SpringTemplateEngine;
|
||||
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
|
||||
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
|
||||
import org.thymeleaf.spring6.ISpringTemplateEngine;
|
||||
import org.thymeleaf.spring6.SpringTemplateEngine;
|
||||
import org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver;
|
||||
import org.thymeleaf.spring6.view.ThymeleafViewResolver;
|
||||
import org.thymeleaf.templatemode.TemplateMode;
|
||||
import org.thymeleaf.templateresolver.ITemplateResolver;
|
||||
|
||||
|
@ -1,14 +1,15 @@
|
||||
plugins {
|
||||
id "java"
|
||||
id "nebula.integtest" version "7.0.9"
|
||||
id "org.gretty" version "3.0.3"
|
||||
id "nebula.integtest" version "8.2.0"
|
||||
id "org.gretty" version "3.0.6"
|
||||
id "war"
|
||||
}
|
||||
|
||||
apply from: "gradle/gretty.gradle"
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
maven { url "https://repo.spring.io/milestone" }
|
||||
maven { url "https://repo.spring.io/snapshot" }
|
||||
}
|
||||
|
||||
@ -29,9 +30,10 @@ dependencies {
|
||||
|
||||
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
|
||||
|
||||
integTestImplementation "org.seleniumhq.selenium:htmlunit-driver:2.44.0"
|
||||
integTestImplementation "org.seleniumhq.selenium:htmlunit-driver:3.64.0"
|
||||
}
|
||||
|
||||
tasks.withType(Test).configureEach {
|
||||
useJUnitPlatform()
|
||||
outputs.upToDateWhen { false }
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
@ -16,15 +16,16 @@
|
||||
package example;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
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 SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
public class SecurityConfiguration {
|
||||
|
||||
// @formatter:off
|
||||
@Bean
|
||||
|
@ -1,14 +1,15 @@
|
||||
plugins {
|
||||
id "java"
|
||||
id "nebula.integtest" version "7.0.9"
|
||||
id "org.gretty" version "3.0.3"
|
||||
id "nebula.integtest" version "8.2.0"
|
||||
id "org.gretty" version "3.0.6"
|
||||
id "war"
|
||||
}
|
||||
|
||||
apply from: "gradle/gretty.gradle"
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
maven { url "https://repo.spring.io/milestone" }
|
||||
maven { url "https://repo.spring.io/snapshot" }
|
||||
}
|
||||
|
||||
@ -31,9 +32,10 @@ dependencies {
|
||||
|
||||
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
|
||||
|
||||
integTestImplementation "org.seleniumhq.selenium:htmlunit-driver:2.44.0"
|
||||
integTestImplementation "org.seleniumhq.selenium:htmlunit-driver:3.64.0"
|
||||
}
|
||||
|
||||
tasks.withType(Test).configureEach {
|
||||
useJUnitPlatform()
|
||||
outputs.upToDateWhen { false }
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
@ -34,7 +34,8 @@ public class DataSourceConfiguration {
|
||||
@Bean
|
||||
public DataSource dataSource() {
|
||||
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
|
||||
return builder.setType(EmbeddedDatabaseType.HSQL).build();
|
||||
return builder.setType(EmbeddedDatabaseType.HSQL)
|
||||
.addScript("classpath:org/springframework/security/core/userdetails/jdbc/users.ddl").build();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,28 +17,29 @@ package example;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
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.provisioning.JdbcUserDetailsManager;
|
||||
import org.springframework.security.provisioning.UserDetailsManager;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
public class SecurityConfiguration {
|
||||
|
||||
@Autowired
|
||||
DataSource dataSource;
|
||||
|
||||
// @formatter:off
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.jdbcAuthentication()
|
||||
.dataSource(this.dataSource)
|
||||
.withDefaultSchema()
|
||||
.withUser(User.withDefaultPasswordEncoder().username("user").password("password").roles("USER"))
|
||||
.withUser(User.withDefaultPasswordEncoder().username("admin").password("password").roles("ADMIN", "USER"));
|
||||
@Bean
|
||||
UserDetailsManager users(DataSource dataSource) {
|
||||
UserDetails user = User.builder().username("user")
|
||||
.password("{bcrypt}$2a$10$AiyMWI4UBLozgXq6itzyVuxrtofjcPzn/WS3fOrcqgzdax9jB7Io.").roles("USER").build();
|
||||
UserDetails admin = User.builder().username("admin")
|
||||
.password("{bcrypt}$2a$10$AiyMWI4UBLozgXq6itzyVuxrtofjcPzn/WS3fOrcqgzdax9jB7Io.").roles("USER", "ADMIN")
|
||||
.build();
|
||||
JdbcUserDetailsManager users = new JdbcUserDetailsManager(dataSource);
|
||||
users.createUser(user);
|
||||
users.createUser(admin);
|
||||
return users;
|
||||
}
|
||||
// @formatter:on
|
||||
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user