From 6f9efb7e91f25205381a0ac7cc97767d2f904004 Mon Sep 17 00:00:00 2001 From: Greg Turnquist Date: Wed, 4 Oct 2017 11:56:16 -0500 Subject: [PATCH] SWS-994 - Upgrade to Java 8, Spring 5, and everything else Move Spring Web Services to 3.0.0.BUILD-SNAPSHOT Key updates include: * Rebase against Java 8 * Spring 5 * Smack 4.2 * Removal of wss4j 1.x support * Gradle 4.0 * Plugins --- build.gradle | 83 +- circle.yml | 21 +- gradle.properties | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 53637 -> 54712 bytes gradle/wrapper/gradle-wrapper.properties | 4 +- gradlew | 100 ++- gradlew.bat | 14 +- .../client/core/WebServiceTemplateTest.java | 6 +- .../soap11/AbstractSoap11MessageTestCase.java | 2 +- .../soap12/AbstractSoap12MessageTestCase.java | 2 +- .../ws/support/TestUtilities.java | 37 - ...rviceMessageReceiverObjectSupportTest.java | 13 +- .../ws/soap/security/wss4j/Wss4jHandler.java | 124 --- .../wss4j/Wss4jSecurityFaultException.java | 38 - .../wss4j/Wss4jSecurityInterceptor.java | 770 ------------------ .../Wss4jSecuritySecurementException.java | 41 - .../Wss4jSecurityValidationException.java | 41 - .../AbstractWsPasswordCallbackHandler.java | 172 ---- .../callback/KeyStoreCallbackHandler.java | 123 --- ...mplePasswordValidationCallbackHandler.java | 70 -- ...rityPasswordValidationCallbackHandler.java | 116 --- .../UsernameTokenPrincipalCallback.java | 50 -- .../soap/security/wss4j/callback/package.html | 5 - .../ws/soap/security/wss4j/package.html | 6 - .../wss4j/support/CryptoFactoryBean.java | 196 ----- .../soap/security/wss4j/support/package.html | 5 - .../wss4j/AxiomWss4jInterceptorTest.java | 21 - ...Wss4jMessageInterceptorEncryptionTest.java | 21 - ...xiomWss4jMessageInterceptorHeaderTest.java | 21 - .../AxiomWss4jMessageInterceptorSignTest.java | 21 - ...Wss4jMessageInterceptorSoapActionTest.java | 21 - ...ptorSpringSecurityCallbackHandlerTest.java | 22 - ...mWss4jMessageInterceptorTimestampTest.java | 21 - ...InterceptorUsernameTokenSignatureTest.java | 22 - ...4jMessageInterceptorUsernameTokenTest.java | 21 - .../AxiomWss4jMessageInterceptorX509Test.java | 22 - .../wss4j/SaajWss4jInterceptorTest.java | 21 - ...Wss4jMessageInterceptorEncryptionTest.java | 21 - ...SaajWss4jMessageInterceptorHeaderTest.java | 21 - .../SaajWss4jMessageInterceptorSignTest.java | 83 -- ...Wss4jMessageInterceptorSoapActionTest.java | 21 - ...ptorSpringSecurityCallbackHandlerTest.java | 22 - ...jWss4jMessageInterceptorTimestampTest.java | 21 - ...InterceptorUsernameTokenSignatureTest.java | 22 - ...4jMessageInterceptorUsernameTokenTest.java | 21 - .../SaajWss4jMessageInterceptorX509Test.java | 22 - .../wss4j/Wss4jInterceptorTestCase.java | 84 -- ...jMessageInterceptorEncryptionTestCase.java | 86 -- ...Wss4jMessageInterceptorHeaderTestCase.java | 160 ---- .../Wss4jMessageInterceptorSignTestCase.java | 123 --- ...jMessageInterceptorSoapActionTestCase.java | 108 --- ...SpringSecurityCallbackHandlerTestCase.java | 127 --- ...4jMessageInterceptorTimestampTestCase.java | 103 --- ...rceptorUsernameTokenSignatureTestCase.java | 45 - ...ssageInterceptorUsernameTokenTestCase.java | 155 ---- .../Wss4jMessageInterceptorX509TestCase.java | 72 -- .../ws/soap/security/wss4j/Wss4jTestCase.java | 281 ------- .../callback/KeyStoreCallbackHandlerTest.java | 56 -- ...PasswordValidationCallbackHandlerTest.java | 81 -- .../wss4j/support/CryptoFactoryBeanTest.java | 67 -- .../soap/security/wss4j2/Wss4jTestCase.java | 16 +- .../transport/xmpp/XmppMessageReceiver.java | 8 +- .../xmpp/XmppReceiverConnection.java | 2 + .../transport/xmpp/XmppSenderConnection.java | 31 +- .../support/XmppConnectionFactoryBean.java | 21 +- .../xmpp/support/XmppTransportUtils.java | 3 +- spring4-next-profile.gradle | 6 - spring5-profile.gradle | 15 - springnext-profile.gradle | 10 + 69 files changed, 182 insertions(+), 4007 deletions(-) delete mode 100644 spring-ws-core/src/test/java/org/springframework/ws/support/TestUtilities.java delete mode 100644 spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jHandler.java delete mode 100644 spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jSecurityFaultException.java delete mode 100644 spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jSecurityInterceptor.java delete mode 100644 spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jSecuritySecurementException.java delete mode 100644 spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jSecurityValidationException.java delete mode 100644 spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/AbstractWsPasswordCallbackHandler.java delete mode 100644 spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/KeyStoreCallbackHandler.java delete mode 100644 spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SimplePasswordValidationCallbackHandler.java delete mode 100644 spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SpringSecurityPasswordValidationCallbackHandler.java delete mode 100644 spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/UsernameTokenPrincipalCallback.java delete mode 100644 spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/package.html delete mode 100644 spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/package.html delete mode 100644 spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/support/CryptoFactoryBean.java delete mode 100644 spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/support/package.html delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jInterceptorTest.java delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorEncryptionTest.java delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorHeaderTest.java delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorSignTest.java delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorSoapActionTest.java delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorSpringSecurityCallbackHandlerTest.java delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorTimestampTest.java delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorUsernameTokenSignatureTest.java delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorUsernameTokenTest.java delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorX509Test.java delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jInterceptorTest.java delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorEncryptionTest.java delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorHeaderTest.java delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorSignTest.java delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorSoapActionTest.java delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorSpringSecurityCallbackHandlerTest.java delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorTimestampTest.java delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorUsernameTokenSignatureTest.java delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorUsernameTokenTest.java delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorX509Test.java delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jInterceptorTestCase.java delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorEncryptionTestCase.java delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorHeaderTestCase.java delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorSignTestCase.java delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorSoapActionTestCase.java delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorSpringSecurityCallbackHandlerTestCase.java delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorTimestampTestCase.java delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorUsernameTokenSignatureTestCase.java delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorUsernameTokenTestCase.java delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorX509TestCase.java delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jTestCase.java delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/callback/KeyStoreCallbackHandlerTest.java delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/callback/SpringSecurityPasswordValidationCallbackHandlerTest.java delete mode 100644 spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/support/CryptoFactoryBeanTest.java delete mode 100644 spring4-next-profile.gradle delete mode 100644 spring5-profile.gradle create mode 100644 springnext-profile.gradle diff --git a/build.gradle b/build.gradle index e59c59de..01c38020 100644 --- a/build.gradle +++ b/build.gradle @@ -3,19 +3,23 @@ buildscript { maven { url 'http://repo.springsource.org/plugins-release' } } dependencies { - classpath 'org.springframework.build.gradle:propdeps-plugin:0.0.7' + classpath 'io.spring.gradle:propdeps-plugin:0.0.9.RELEASE' classpath 'io.spring.gradle:docbook-reference-plugin:0.3.1' - classpath 'io.spring.gradle:spring-io-plugin:0.0.4.RELEASE' + classpath 'io.spring.gradle:spring-io-plugin:0.0.8.RELEASE' } } configure(allprojects) { group = "org.springframework.ws" - ext.springVersion = "4.2.9.RELEASE" - ext.springSecurityVersion = "4.0.4.RELEASE" + ext.springVersion = "5.0.0.RELEASE" + ext.springSecurityVersion = "5.0.0.M4" ext.axiomVersion = "1.2.20" - ext.smackVersion = "4.1.9" + ext.smackVersion = "4.2.1" + ext.sunMailVersion = "1.6.0" + ext.xmlSchemaCoreVersion = "2.2.2" + ext.commonsHttpclientVersion = "3.1" + ext.aspectjVersion = "1.8.11" apply plugin: "java" @@ -35,8 +39,8 @@ configure(allprojects) { "-Xlint:-unchecked", "-Xlint:-options"] compileJava { - sourceCompatibility=1.7 - targetCompatibility=1.7 + sourceCompatibility=1.8 + targetCompatibility=1.8 } sourceSets.test.resources.srcDirs = ['src/test/resources', 'src/test/java'] @@ -49,22 +53,19 @@ configure(allprojects) { exclude '**/*Abstract*.*' } - repositories { - maven { url 'https://repo.spring.io/libs-release' } - } - dependencies { - compile("commons-logging:commons-logging:1.1.3") + compile("commons-logging:commons-logging:1.2") compile("org.springframework:spring-core:$springVersion") testCompile("junit:junit:4.12") testCompile("org.easymock:easymock:3.1") testCompile("xmlunit:xmlunit:1.5") - testCompile("com.sun.mail:javax.mail:1.5.4") + testCompile("com.sun.mail:javax.mail:$sunMailVersion") testRuntime("org.codehaus.woodstox:woodstox-core-asl:4.2.0") } ext.javadocLinks = [ + "http://docs.oracle.com/javase/8/docs/api/", "http://docs.oracle.com/javase/7/docs/api/", "http://docs.oracle.com/javaee/6/api/", "http://docs.spring.io/spring/docs/current/javadoc-api/", @@ -84,10 +85,14 @@ configure(subprojects) { subproject -> apply plugin: "propdeps-maven" apply from: "${rootProject.projectDir}/publish-maven.gradle" + repositories { + maven { url "https://repo.spring.io/libs-snapshot" } + maven { url "https://repo.spring.io/libs-release" } + } + /** * To run an alternate profile... - * ./gradlew -Pprofile=spring4-next clean build - * ./gradlew -Pprofile=spring5 clean build + * ./gradlew -Pprofile=springnext clean build */ if (project.hasProperty('profile')) { apply from: "${project.rootDir}/${profile}-profile.gradle" @@ -168,7 +173,7 @@ project('spring-xml') { compile("org.springframework:spring-context:$springVersion") //XML - optional("org.apache.ws.xmlschema:xmlschema-core:2.1.0") + optional("org.apache.ws.xmlschema:xmlschema-core:$xmlSchemaCoreVersion") optional("jaxen:jaxen:1.1.4") } } @@ -187,14 +192,14 @@ project('spring-ws-core') { testCompile("org.springframework:spring-test:$springVersion") // XML - optional("org.jdom:jdom2:2.0.5") + optional("org.jdom:jdom2:2.0.6") optional("dom4j:dom4j:1.6.1") optional("xom:xom:1.2.5") { exclude group: 'xml-apis', module: 'xml-apis' exclude group: 'xerces', module: 'xercesImpl' exclude group: 'xalan', module: 'xalan' } - optional("org.apache.ws.xmlschema:xmlschema-core:2.1.0") + optional("org.apache.ws.xmlschema:xmlschema-core:$xmlSchemaCoreVersion") // SOAP optional("org.apache.ws.commons.axiom:axiom-api:$axiomVersion") @@ -203,17 +208,19 @@ project('spring-ws-core') { } // WSDL - optional("wsdl4j:wsdl4j:1.6.1") + optional("wsdl4j:wsdl4j:1.6.3") // Transport - provided("javax.servlet:javax.servlet-api:3.0.1") - optional("org.apache.httpcomponents:httpclient:4.3.4") - optional("commons-httpclient:commons-httpclient:3.1") - testCompile("org.mortbay.jetty:jetty:6.1.26") + provided("javax.servlet:javax.servlet-api:3.1.0") + optional("org.apache.httpcomponents:httpclient:4.5.3") + optional("commons-httpclient:commons-httpclient:$commonsHttpclientVersion") + testCompile("org.mortbay.jetty:jetty:6.1.26") { + exclude group: 'org.mortbay.jetty', module: 'servlet-api' + } - testCompile("log4j:log4j:1.2.16") - testCompile("org.aspectj:aspectjrt:1.6.9") - testRuntime("org.aspectj:aspectjweaver:1.6.9") + testCompile("log4j:log4j:1.2.17") + testCompile("org.aspectj:aspectjrt:$aspectjVersion") + testRuntime("org.aspectj:aspectjweaver:$aspectjVersion") } } @@ -229,17 +236,17 @@ project('spring-ws-support') { testCompile("org.springframework:spring-test:$springVersion") // Transport - provided("javax.jms:jms-api:1.1-rev-1") - provided("javax.mail:javax.mail-api:1.4.7") - provided("com.sun.mail:javax.mail:1.4.7") + provided("javax.jms:javax.jms-api:2.0.1") + provided("javax.mail:javax.mail-api:1.6.0") + provided("com.sun.mail:javax.mail:$sunMailVersion") optional("org.igniterealtime.smack:smack-tcp:$smackVersion") optional("org.igniterealtime.smack:smack-java7:$smackVersion") optional("org.igniterealtime.smack:smack-extensions:$smackVersion") - testCompile("commons-httpclient:commons-httpclient:3.1") - testRuntime("org.apache.activemq:activemq-core:4.1.2") { + testCompile("commons-httpclient:commons-httpclient:$commonsHttpclientVersion") + testRuntime("org.apache.activemq:activemq-core:5.7.0") { exclude group:'org.apache.geronimo.specs', module:'geronimo-jms_1.1_spec' } - testCompile("org.jvnet.mock-javamail:mock-javamail:1.6") { + testCompile("org.jvnet.mock-javamail:mock-javamail:1.9") { exclude group:'javax.mail', module:'mail' } } @@ -258,18 +265,17 @@ project('spring-ws-security') { // Spring Security compile("org.springframework.security:spring-security-core:$springSecurityVersion") - optional("net.sf.ehcache:ehcache:2.8.4") + optional("net.sf.ehcache:ehcache:2.10.4") // WS-Security optional("com.sun.xml.wss:xws-security:3.0") { exclude group: 'javax.xml.crypto', module: 'xmldsig' } - compile("org.apache.ws.security:wss4j:1.6.19") - compile("org.apache.wss4j:wss4j-ws-security-dom:2.1.4") + compile("org.apache.wss4j:wss4j-ws-security-dom:2.2.0") // SOAP - provided("com.sun.xml.messaging.saaj:saaj-impl:1.3.19") // required for XWSS + provided("com.sun.xml.messaging.saaj:saaj-impl:1.3.28") // required for XWSS optional("org.apache.ws.commons.axiom:axiom-api:$axiomVersion") optional("org.apache.ws.commons.axiom:axiom-impl:$axiomVersion") { exclude group: 'org.codehaus.woodstox', module: 'wstx-asl' @@ -461,9 +467,4 @@ configure(rootProject) { archives schemaZip archives distZip } - - task wrapper(type: Wrapper) { - description = 'Generates gradlew[.bat] scripts' - gradleVersion = '2.8' - } } diff --git a/circle.yml b/circle.yml index 61e4b874..ddb9c9ab 100644 --- a/circle.yml +++ b/circle.yml @@ -1,3 +1,12 @@ +version: 2 +jobs: + build: + docker: + - image: circleci/openjdk:8u141 + steps: + - checkout + - run: ./gradlew clean build + - run: ./gradlew -Pprofile=springnext clean build general: branches: ignore: @@ -6,15 +15,3 @@ general: dependencies: cache_directories: - "~/.m2" - -machine: - java: - version: oraclejdk8 - environment: - _JAVA_OPTIONS: "-Xms1024m -Xmx2048m" - -test: - override: - - ./gradlew clean build - - ./gradlew -Pprofile=spring4-next clean build - - ./gradlew -Pprofile=spring5 clean build diff --git a/gradle.properties b/gradle.properties index 063615bb..7645a9fa 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1 @@ -version=2.4.1.BUILD-SNAPSHOT +version=3.0.0.BUILD-SNAPSHOT diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 05ef575b0cd0173fc735f2857ce4bd594ce4f6bd..f14b21e70948c2354471cb32ed10b50ade558738 100644 GIT binary patch delta 28633 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 delta 27494 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 H-(LM6wqM>l diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ea06ca28..d75e5df7 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Jan 20 16:03:00 CST 2016 +#Wed Oct 04 12:56:30 CDT 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.0.2-bin.zip diff --git a/gradlew b/gradlew index 9d82f789..cccdd3d5 100755 --- a/gradlew +++ b/gradlew @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh ############################################################################## ## @@ -6,42 +6,6 @@ ## ############################################################################## -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn ( ) { - echo "$*" -} - -die ( ) { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; -esac - # Attempt to set APP_HOME # Resolve links: $0 may be a link PRG="$0" @@ -60,6 +24,46 @@ cd "`dirname \"$PRG\"`/" >/dev/null APP_HOME="`pwd -P`" cd "$SAVED" >/dev/null +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -85,7 +89,7 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then +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 @@ -150,11 +154,19 @@ if $cygwin ; then esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " } -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" +APP_ARGS=$(save "$@") -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +# 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" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index aec99730..e95643d6 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -8,14 +8,14 @@ @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome @@ -46,10 +46,9 @@ echo location of your Java installation. goto fail :init -@rem Get command-line arguments, handling Windowz variants +@rem Get command-line arguments, handling Windows variants if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args :win9xME_args @rem Slurp the command line arguments. @@ -60,11 +59,6 @@ set _SKIP=2 if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ :execute @rem Setup the command line diff --git a/spring-ws-core/src/test/java/org/springframework/ws/client/core/WebServiceTemplateTest.java b/spring-ws-core/src/test/java/org/springframework/ws/client/core/WebServiceTemplateTest.java index bcbbeef5..b353b2fa 100644 --- a/spring-ws-core/src/test/java/org/springframework/ws/client/core/WebServiceTemplateTest.java +++ b/spring-ws-core/src/test/java/org/springframework/ws/client/core/WebServiceTemplateTest.java @@ -34,7 +34,6 @@ import org.springframework.ws.client.support.destination.DestinationProvider; import org.springframework.ws.client.support.interceptor.ClientInterceptor; import org.springframework.ws.context.DefaultMessageContext; import org.springframework.ws.context.MessageContext; -import org.springframework.ws.support.TestUtilities; import org.springframework.ws.transport.FaultAwareWebServiceConnection; import org.springframework.ws.transport.WebServiceConnection; import org.springframework.ws.transport.WebServiceMessageSender; @@ -486,13 +485,10 @@ public class WebServiceTemplateTest { reset(connectionMock); - if (!TestUtilities.SPRING5) { - expect(connectionMock.getUri()).andReturn(providerUri); - } - connectionMock.send(isA(WebServiceMessage.class)); expect(connectionMock.hasError()).andReturn(false); expect(connectionMock.receive(messageFactory)).andReturn(null); + expect(connectionMock.getUri()).andReturn(new URI("http://example.com")); connectionMock.close(); replay(connectionMock, extractorMock, providerMock); diff --git a/spring-ws-core/src/test/java/org/springframework/ws/soap/soap11/AbstractSoap11MessageTestCase.java b/spring-ws-core/src/test/java/org/springframework/ws/soap/soap11/AbstractSoap11MessageTestCase.java index 4375fcfe..0da1d2e7 100644 --- a/spring-ws-core/src/test/java/org/springframework/ws/soap/soap11/AbstractSoap11MessageTestCase.java +++ b/spring-ws-core/src/test/java/org/springframework/ws/soap/soap11/AbstractSoap11MessageTestCase.java @@ -23,7 +23,7 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.dom.DOMResult; import javax.xml.transform.stream.StreamSource; -import junit.framework.Assert; +import org.junit.Assert; import org.w3c.dom.Document; import org.w3c.dom.Element; diff --git a/spring-ws-core/src/test/java/org/springframework/ws/soap/soap12/AbstractSoap12MessageTestCase.java b/spring-ws-core/src/test/java/org/springframework/ws/soap/soap12/AbstractSoap12MessageTestCase.java index ed8e9115..91ce754a 100644 --- a/spring-ws-core/src/test/java/org/springframework/ws/soap/soap12/AbstractSoap12MessageTestCase.java +++ b/spring-ws-core/src/test/java/org/springframework/ws/soap/soap12/AbstractSoap12MessageTestCase.java @@ -23,7 +23,7 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.dom.DOMResult; import javax.xml.transform.stream.StreamSource; -import junit.framework.Assert; +import org.junit.Assert; import org.w3c.dom.Document; import org.w3c.dom.Element; diff --git a/spring-ws-core/src/test/java/org/springframework/ws/support/TestUtilities.java b/spring-ws-core/src/test/java/org/springframework/ws/support/TestUtilities.java deleted file mode 100644 index 42f9a04d..00000000 --- a/spring-ws-core/src/test/java/org/springframework/ws/support/TestUtilities.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.support; - -import org.springframework.util.ClassUtils; - -/** - * @author Greg Turnquist - */ -public final class TestUtilities { - - public static boolean SPRING5; - - static { - ClassLoader classLoader = TestUtilities.class.getClassLoader(); - try { - ClassUtils.forName("org.springframework.http.server.reactive.ReactorHttpHandlerAdapter", classLoader); - SPRING5 = true; - } catch (ClassNotFoundException e) { - SPRING5 = false; - } - - } -} diff --git a/spring-ws-core/src/test/java/org/springframework/ws/transport/support/WebServiceMessageReceiverObjectSupportTest.java b/spring-ws-core/src/test/java/org/springframework/ws/transport/support/WebServiceMessageReceiverObjectSupportTest.java index 3a0a0dfa..d5904b52 100644 --- a/spring-ws-core/src/test/java/org/springframework/ws/transport/support/WebServiceMessageReceiverObjectSupportTest.java +++ b/spring-ws-core/src/test/java/org/springframework/ws/transport/support/WebServiceMessageReceiverObjectSupportTest.java @@ -28,7 +28,6 @@ import org.springframework.ws.MockWebServiceMessageFactory; import org.springframework.ws.WebServiceMessage; import org.springframework.ws.context.MessageContext; import org.springframework.ws.soap.SoapVersion; -import org.springframework.ws.support.TestUtilities; import org.springframework.ws.transport.FaultAwareWebServiceConnection; import org.springframework.ws.transport.WebServiceMessageReceiver; @@ -55,9 +54,7 @@ public class WebServiceMessageReceiverObjectSupportTest { @Test public void handleConnectionResponse() throws Exception { - if (!TestUtilities.SPRING5) { - expect(connectionMock.getUri()).andReturn(new URI("http://example.com")); - } + expect(connectionMock.getUri()).andReturn(new URI("http://example.com")); expect(connectionMock.receive(messageFactory)).andReturn(request); connectionMock.setFaultCode(null); connectionMock.send(isA(WebServiceMessage.class)); @@ -83,9 +80,7 @@ public class WebServiceMessageReceiverObjectSupportTest { public void handleConnectionFaultResponse() throws Exception { final QName faultCode = SoapVersion.SOAP_11.getClientOrSenderFaultName(); - if (!TestUtilities.SPRING5) { - expect(connectionMock.getUri()).andReturn(new URI("http://example.com")); - } + expect(connectionMock.getUri()).andReturn(new URI("http://example.com")); expect(connectionMock.receive(messageFactory)).andReturn(request); connectionMock.setFaultCode(faultCode); connectionMock.send(isA(WebServiceMessage.class)); @@ -111,9 +106,7 @@ public class WebServiceMessageReceiverObjectSupportTest { @Test public void handleConnectionNoResponse() throws Exception { - if (!TestUtilities.SPRING5) { - expect(connectionMock.getUri()).andReturn(new URI("http://example.com")); - } + expect(connectionMock.getUri()).andReturn(new URI("http://example.com")); expect(connectionMock.receive(messageFactory)).andReturn(request); connectionMock.close(); diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jHandler.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jHandler.java deleted file mode 100644 index a8ca645a..00000000 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jHandler.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2005-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -import java.util.List; -import java.util.Properties; - -import org.apache.ws.security.WSSecurityEngineResult; -import org.apache.ws.security.WSSecurityException; -import org.apache.ws.security.components.crypto.Crypto; -import org.apache.ws.security.handler.RequestData; -import org.apache.ws.security.handler.WSHandler; -import org.apache.ws.security.handler.WSHandlerConstants; -import org.w3c.dom.Document; - -import org.springframework.ws.context.MessageContext; - -/** - * @author Tareq Abed Rabbo - * @author Arjen Poutsma - * @since 1.5.0 - * @deprecated Transition to {@link org.springframework.ws.soap.security.wss4j2.Wss4jHandler}. - */ -@Deprecated -class Wss4jHandler extends WSHandler { - - /** Keys are constants from {@link WSHandlerConstants}; values are strings. */ - private Properties options = new Properties(); - - private String securementPassword; - - private Crypto securementEncryptionCrypto; - - private Crypto securementSignatureCrypto; - - Wss4jHandler() { - // set up default handler properties - options.setProperty(WSHandlerConstants.MUST_UNDERSTAND, Boolean.toString(true)); - options.setProperty(WSHandlerConstants.ENABLE_SIGNATURE_CONFIRMATION, Boolean.toString(true)); - } - - @Override - protected boolean checkReceiverResultsAnyOrder(List wsResult, List actions) { - return super.checkReceiverResultsAnyOrder(wsResult, actions); - } - - void setOption(String key, String value) { - options.setProperty(key, value); - } - - void setOption(String key, boolean value) { - options.setProperty(key, Boolean.toString(value)); - } - - @Override - public Object getOption(String key) { - return options.getProperty(key); - } - - void setSecurementPassword(String securementPassword) { - this.securementPassword = securementPassword; - } - - void setSecurementEncryptionCrypto(Crypto securementEncryptionCrypto) { - this.securementEncryptionCrypto = securementEncryptionCrypto; - } - - void setSecurementSignatureCrypto(Crypto securementSignatureCrypto) { - this.securementSignatureCrypto = securementSignatureCrypto; - } - - @Override - public String getPassword(Object msgContext) { - return securementPassword; - } - - @Override - public Object getProperty(Object msgContext, String key) { - return ((MessageContext) msgContext).getProperty(key); - } - - @Override - protected Crypto loadEncryptionCrypto(RequestData reqData) throws WSSecurityException { - return securementEncryptionCrypto; - } - - @Override - public Crypto loadSignatureCrypto(RequestData reqData) throws WSSecurityException { - return securementSignatureCrypto; - } - - @Override - public void setPassword(Object msgContext, String password) { - securementPassword = password; - } - - @Override - public void setProperty(Object msgContext, String key, Object value) { - ((MessageContext) msgContext).setProperty(key, value); - } - - @Override - protected void doSenderAction(int doAction, - Document doc, - RequestData reqData, - List actions, - boolean isRequest) throws WSSecurityException { - super.doSenderAction(doAction, doc, reqData, actions, isRequest); - } -} diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jSecurityFaultException.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jSecurityFaultException.java deleted file mode 100644 index ab4c6c4b..00000000 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jSecurityFaultException.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2005-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -import javax.xml.namespace.QName; - -import org.springframework.ws.soap.security.WsSecurityFaultException; - -/** - * WSS4J-specific version of the {@link WsSecurityFaultException}. - * - * @author Tareq Abed Rabbo - * @author Arjen Poutsma - * @since 1.5.0 - * @deprecated Transition to {@link org.springframework.ws.soap.security.wss4j2.Wss4jSecurityFaultException} - */ -@SuppressWarnings("serial") -@Deprecated -public class Wss4jSecurityFaultException extends WsSecurityFaultException { - - public Wss4jSecurityFaultException(QName faultCode, String faultString, String faultActor) { - super(faultCode, faultString, faultActor); - } -} diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jSecurityInterceptor.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jSecurityInterceptor.java deleted file mode 100644 index 9102444c..00000000 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jSecurityInterceptor.java +++ /dev/null @@ -1,770 +0,0 @@ -/* - * Copyright 2005-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -import java.io.IOException; -import java.security.Principal; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.List; -import javax.security.auth.callback.Callback; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.callback.UnsupportedCallbackException; - -import org.apache.ws.security.WSConstants; -import org.apache.ws.security.WSSConfig; -import org.apache.ws.security.WSSecurityEngine; -import org.apache.ws.security.WSSecurityEngineResult; -import org.apache.ws.security.WSSecurityException; -import org.apache.ws.security.WSUsernameTokenPrincipal; -import org.apache.ws.security.components.crypto.Crypto; -import org.apache.ws.security.handler.RequestData; -import org.apache.ws.security.handler.WSHandlerConstants; -import org.apache.ws.security.handler.WSHandlerResult; -import org.apache.ws.security.message.token.Timestamp; -import org.apache.ws.security.saml.SAMLIssuer; -import org.apache.ws.security.util.WSSecurityUtil; -import org.apache.ws.security.validate.Credential; -import org.apache.ws.security.validate.SignatureTrustValidator; -import org.apache.ws.security.validate.TimestampValidator; -import org.w3c.dom.Document; - -import org.springframework.beans.factory.InitializingBean; -import org.springframework.util.Assert; -import org.springframework.util.CollectionUtils; -import org.springframework.util.StringUtils; -import org.springframework.ws.context.MessageContext; -import org.springframework.ws.soap.SoapMessage; -import org.springframework.ws.soap.security.AbstractWsSecurityInterceptor; -import org.springframework.ws.soap.security.WsSecuritySecurementException; -import org.springframework.ws.soap.security.WsSecurityValidationException; -import org.springframework.ws.soap.security.callback.CallbackHandlerChain; -import org.springframework.ws.soap.security.callback.CleanupCallback; -import org.springframework.ws.soap.security.wss4j.callback.UsernameTokenPrincipalCallback; - -/** - * A WS-Security endpoint interceptor based on Apache's WSS4J. This interceptor supports messages created by the {@link - * org.springframework.ws.soap.axiom.AxiomSoapMessageFactory} and the {@link org.springframework.ws.soap.saaj.SaajSoapMessageFactory}. - * - *

The validation and securement actions executed by this interceptor are configured via {@code validationActions} - * and {@code securementActions} properties, respectively. Actions should be passed as a space-separated strings. - * - *

Valid validation actions are: - * - *

- * - * - * - * - * - * - * - *
Validation actionDescription
{@code UsernameToken}Validates username token
{@code Timestamp}Validates the timestamp
{@code Encrypt}Decrypts the message
{@code Signature}Validates the signature
{@code NoSecurity}No action performed
- *

- * Securement actions are: - * - *

- * - * - * - * - * - * - * - * - *
Securement actionDescription
{@code UsernameToken}Adds a username token
{@code UsernameTokenSignature}Adds a username token and a signature username token secret key
{@code Timestamp}Adds a timestamp
{@code Encrypt}Encrypts the response
{@code Signature}Signs the response
{@code NoSecurity}No action performed
- * - *

The order of the actions that the client performed to secure the messages is significant and is enforced by the - * interceptor. - * - * @author Tareq Abed Rabbo - * @author Arjen Poutsma - * @author Greg Turnquist - * @see Apache WSS4J - * @since 1.5.0 - * @deprecated Transition to {@link org.springframework.ws.soap.security.wss4j2.Wss4jSecurityInterceptor} - */ -@Deprecated -public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor implements InitializingBean { - - public static final String SECUREMENT_USER_PROPERTY_NAME = "Wss4jSecurityInterceptor.securementUser"; - - private static final String SAML_ISSUER_PROPERTY_NAME = "Wss4jSecurityInterceptor.samlIssuer"; - - private int securementAction; - - private String securementActions; - - private List securementActionsVector; - - private String securementUsername; - - private CallbackHandler validationCallbackHandler; - - private int validationAction; - - private String validationActions; - - private List validationActionsVector; - - private String validationActor; - - private Crypto validationDecryptionCrypto; - - private Crypto validationSignatureCrypto; - - private boolean timestampStrict = true; - - private boolean enableSignatureConfirmation; - - private int validationTimeToLive = 300; - - private int securementTimeToLive = 300; - - private int futureTimeToLive = 60; - - private SAMLIssuer samlIssuer; - - private WSSConfig wssConfig; - - private final Wss4jHandler handler = new Wss4jHandler(); - - private final WSSecurityEngine securityEngine = new WSSecurityEngine(); - - private boolean enableRevocation; - - private boolean bspCompliant; - - private boolean securementUseDerivedKey; - - // To maintain same behavior as default, this flag is set to true - private boolean removeSecurityHeader = true; - - public void setSecurementActions(String securementActions) { - this.securementActions = securementActions; - securementActionsVector = new ArrayList(); - try { - securementAction = WSSecurityUtil.decodeAction(securementActions, securementActionsVector); - } - catch (WSSecurityException ex) { - throw new IllegalArgumentException(ex); - } - } - - /** - * The actor name of the {@code wsse:Security} header. - * - *

If this parameter is omitted, the actor name is not set. - * - *

The value of the actor or role has to match the receiver's setting or may contain standard values. - */ - public void setSecurementActor(String securementActor) { - handler.setOption(WSHandlerConstants.ACTOR, securementActor); - } - - public void setSecurementEncryptionCrypto(Crypto securementEncryptionCrypto) { - handler.setSecurementEncryptionCrypto(securementEncryptionCrypto); - } - - /** Sets the key name that needs to be sent for encryption. */ - public void setSecurementEncryptionEmbeddedKeyName(String securementEncryptionEmbeddedKeyName) { - handler.setOption(WSHandlerConstants.ENC_KEY_NAME, securementEncryptionEmbeddedKeyName); - } - - /** - * Defines which key identifier type to use. The WS-Security specifications recommends to use the identifier type - * {@code IssuerSerial}. For possible encryption key identifier types refer to {@link - * org.apache.ws.security.handler.WSHandlerConstants#keyIdentifier}. For encryption {@code IssuerSerial}, - * {@code X509KeyIdentifier}, {@code DirectReference}, {@code Thumbprint}, - * {@code SKIKeyIdentifier}, and {@code EmbeddedKeyName} are valid only. - */ - public void setSecurementEncryptionKeyIdentifier(String securementEncryptionKeyIdentifier) { - handler.setOption(WSHandlerConstants.ENC_KEY_ID, securementEncryptionKeyIdentifier); - } - - /** - * Defines which algorithm to use to encrypt the generated symmetric key. Currently WSS4J supports {@link - * WSConstants#KEYTRANSPORT_RSA15} and {@link WSConstants#KEYTRANSPORT_RSAOEP}. - */ - public void setSecurementEncryptionKeyTransportAlgorithm(String securementEncryptionKeyTransportAlgorithm) { - handler.setOption(WSHandlerConstants.ENC_KEY_TRANSPORT, securementEncryptionKeyTransportAlgorithm); - } - - /** - * Property to define which parts of the request shall be encrypted. - * - *

The value of this property is a list of semicolon separated element names that identify the elements to encrypt. - * An encryption mode specifier and a namespace identification, each inside a pair of curly brackets, may precede - * each element name. - * - *

The encryption mode specifier is either {@code {Content}} or {@code {Element}}. Please refer to the W3C - * XML Encryption specification about the differences between Element and Content encryption. The encryption mode - * defaults to {@code Content} if it is omitted. Example of a list: - *

-	 * <property name="securementEncryptionParts"
-	 *	 value="{Content}{http://example.org/paymentv2}CreditCard;
-	 *			   {Element}{}UserName" />
-	 * 
- * The first entry of the list identifies the element {@code CreditCard} in the namespace - * {@code http://example.org/paymentv2}, and will encrypt its content. Be aware that the element name, the - * namespace identifier, and the encryption modifier are case sensitive. - * - *

The encryption modifier and the namespace identifier can be omitted. In this case the encryption mode defaults to - * {@code Content} and the namespace is set to the SOAP namespace. - * - *

An empty encryption mode defaults to {@code Content}, an empty namespace identifier defaults to the SOAP - * namespace. The second line of the example defines {@code Element} as encryption mode for an - * {@code UserName} element in the SOAP namespace. - * - *

To specify an element without a namespace use the string {@code Null} as the namespace name (this is a case - * sensitive string) - * - *

If no list is specified, the handler encrypts the SOAP Body in {@code Content} mode by default. - */ - public void setSecurementEncryptionParts(String securementEncryptionParts) { - handler.setOption(WSHandlerConstants.ENCRYPTION_PARTS, securementEncryptionParts); - } - - /** - * Defines which symmetric encryption algorithm to use. WSS4J supports the following alorithms: {@link - * WSConstants#TRIPLE_DES}, {@link WSConstants#AES_128}, {@link WSConstants#AES_256}, and {@link - * WSConstants#AES_192}. Except for AES 192 all of these algorithms are required by the XML Encryption - * specification. - */ - public void setSecurementEncryptionSymAlgorithm(String securementEncryptionSymAlgorithm) { - this.handler.setOption(WSHandlerConstants.ENC_SYM_ALGO, securementEncryptionSymAlgorithm); - } - - /** - * The user's name for encryption. - * - *

The encryption functions uses the public key of this user's certificate to encrypt the generated symmetric key. - * - *

If this parameter is not set, then the encryption function falls back to the {@link - * org.apache.ws.security.handler.WSHandlerConstants#USER} parameter to get the certificate. - * - *

If only encryption of the SOAP body data is requested, it is recommended to use this parameter to define - * the username. The application can then use the standard user and password functions (see example at {@link - * org.apache.ws.security.handler.WSHandlerConstants#USER} to enable HTTP authentication functions. - * - *

Encryption only does not authenticate a user / sender, therefore it does not need a password. - * - *

Placing the username of the encryption certificate in the configuration file is not a security risk, because the - * public key of that certificate is used only. - */ - public void setSecurementEncryptionUser(String securementEncryptionUser) { - handler.setOption(WSHandlerConstants.ENCRYPTION_USER, securementEncryptionUser); - } - - public void setSecurementPassword(String securementPassword) { - this.handler.setSecurementPassword(securementPassword); - } - - /** - * Specific parameter for UsernameToken action to define the encoding of the passowrd. - * - *

The parameter can be set to either {@link WSConstants#PW_DIGEST} or to {@link WSConstants#PW_TEXT}. - * - *

The default setting is PW_DIGEST. - */ - public void setSecurementPasswordType(String securementUsernameTokenPasswordType) { - handler.setOption(WSHandlerConstants.PASSWORD_TYPE, securementUsernameTokenPasswordType); - } - - /** - * Defines which signature algorithm to use. - * @see WSConstants#RSA - * @see WSConstants#DSA - */ - public void setSecurementSignatureAlgorithm(String securementSignatureAlgorithm) { - handler.setOption(WSHandlerConstants.SIG_ALGO, securementSignatureAlgorithm); - } - - /** - * Defines which signature digest algorithm to use. - */ - public void setSecurementSignatureDigestAlgorithm(String digestAlgorithm) { - handler.setOption(WSHandlerConstants.SIG_DIGEST_ALGO, digestAlgorithm); - } - - public void setSecurementSignatureCrypto(Crypto securementSignatureCrypto) { - handler.setSecurementSignatureCrypto(securementSignatureCrypto); - } - - /** - * Defines which key identifier type to use. The WS-Security specifications recommends to use the identifier type - * {@code IssuerSerial}. For possible signature key identifier types refer to {@link - * org.apache.ws.security.handler.WSHandlerConstants#keyIdentifier}. For signature {@code IssuerSerial} and - * {@code DirectReference} are valid only. - */ - public void setSecurementSignatureKeyIdentifier(String securementSignatureKeyIdentifier) { - handler.setOption(WSHandlerConstants.SIG_KEY_ID, securementSignatureKeyIdentifier); - } - - /** - * Property to define which parts of the request shall be signed. - * - *

Refer to {@link #setSecurementEncryptionParts(String)} for a detailed description of the format of the value - * string. - * - *

If this property is not specified the handler signs the SOAP Body by default. - * - *

The WS Security specifications define several formats to transfer the signature tokens (certificates) or - * references to these tokens. Thus, the plain element name {@code Token} signs the token and takes care of the - * different formats. - * - *

To sign the SOAP body and the signature token the value of this parameter must contain: - *

-	 * <property name="securementSignatureParts"
-	 *	 value="{}{http://schemas.xmlsoap.org/soap/envelope/}Body; Token" />
-	 * 
- * To specify an element without a namespace use the string {@code Null} as the namespace name (this is a case - * sensitive string) - * - *

If there is no other element in the request with a local name of {@code Body} then the SOAP namespace - * identifier can be empty ({@code {}}). - */ - public void setSecurementSignatureParts(String securementSignatureParts) { - handler.setOption(WSHandlerConstants.SIGNATURE_PARTS, securementSignatureParts); - } - - /** - * The user's name for signature. - * - *

This name is used as the alias name in the keystore to get user's - * certificate and private key to perform signing. - * - *

If this parameter is not set, then the signature - * function falls back to the alias specified by {@link #setSecurementUsername(String)}. - * - */ - public void setSecurementSignatureUser(String securementSignatureUser) { - handler.setOption(WSHandlerConstants.SIGNATURE_USER, securementSignatureUser); - } - - /** Sets the username for securement username token or/and the alias of the private key for securement signature */ - public void setSecurementUsername(String securementUsername) { - this.securementUsername = securementUsername; - } - - /** Sets the time to live on the outgoing message */ - public void setSecurementTimeToLive(int securementTimeToLive) { - if (securementTimeToLive <= 0) { - throw new IllegalArgumentException("timeToLive must be positive"); - } - this.securementTimeToLive = securementTimeToLive; - } - - /** - * Enables the derivation of keys as per the UsernameTokenProfile 1.1 spec. Default is {@code true}. - */ - public void setSecurementUseDerivedKey(boolean securementUseDerivedKey) { - this.securementUseDerivedKey = securementUseDerivedKey; - } - - /** Sets the server-side time to live */ - public void setValidationTimeToLive(int validationTimeToLive) { - if (validationTimeToLive <= 0) { - throw new IllegalArgumentException("timeToLive must be positive"); - } - this.validationTimeToLive = validationTimeToLive; - } - - /** Sets the validation actions to be executed by the interceptor. */ - public void setValidationActions(String actions) { - this.validationActions = actions; - try { - validationActionsVector = new ArrayList(); - validationAction = WSSecurityUtil.decodeAction(actions, validationActionsVector); - } - catch (WSSecurityException ex) { - throw new IllegalArgumentException(ex); - } - } - - public void setValidationActor(String validationActor) { - this.validationActor = validationActor; - } - - /** - * Sets the {@link org.apache.ws.security.WSPasswordCallback} handler to use when validating messages. - * - * @see #setValidationCallbackHandlers(CallbackHandler[]) - */ - public void setValidationCallbackHandler(CallbackHandler callbackHandler) { - this.validationCallbackHandler = callbackHandler; - } - - /** - * Sets the {@link org.apache.ws.security.WSPasswordCallback} handlers to use when validating messages. - * - * @see #setValidationCallbackHandler(CallbackHandler) - */ - public void setValidationCallbackHandlers(CallbackHandler[] callbackHandler) { - this.validationCallbackHandler = new CallbackHandlerChain(callbackHandler); - } - - /** Sets the Crypto to use to decrypt incoming messages */ - public void setValidationDecryptionCrypto(Crypto decryptionCrypto) { - this.validationDecryptionCrypto = decryptionCrypto; - } - - /** Sets the Crypto to use to verify the signature of incoming messages */ - public void setValidationSignatureCrypto(Crypto signatureCrypto) { - this.validationSignatureCrypto = signatureCrypto; - } - - /** Whether to enable signatureConfirmation or not. By default signatureConfirmation is enabled */ - public void setEnableSignatureConfirmation(boolean enableSignatureConfirmation) { - handler.setOption(WSHandlerConstants.ENABLE_SIGNATURE_CONFIRMATION, enableSignatureConfirmation); - this.enableSignatureConfirmation = enableSignatureConfirmation; - } - - /** Sets if the generated timestamp header's precision is in milliseconds. */ - public void setTimestampPrecisionInMilliseconds(boolean timestampPrecisionInMilliseconds) { - handler.setOption(WSHandlerConstants.TIMESTAMP_PRECISION, timestampPrecisionInMilliseconds); - } - - /** Sets whether or not timestamp verification is done with the server-side time to live */ - public void setTimestampStrict(boolean timestampStrict) { - this.timestampStrict = timestampStrict; - } - - /** - * Enables the {@code mustUnderstand} attribute on WS-Security headers on outgoing messages. Default is - * {@code true}. - */ - public void setSecurementMustUnderstand(boolean securementMustUnderstand) { - handler.setOption(WSHandlerConstants.MUST_UNDERSTAND, securementMustUnderstand); - } - - /** - * Sets the additional elements in {@code UsernameToken}s. - * - *

The value of this parameter is a list of element names that are added to the UsernameToken. The names of the list - * a separated by spaces. - * - *

The list may contain the names {@code Nonce} and {@code Created} only (case sensitive). Use this option - * if the password type is {@code passwordText} and the handler shall add the {@code Nonce} and/or - * {@code Created} elements. - */ - public void setSecurementUsernameTokenElements(String securementUsernameTokenElements) { - handler.setOption(WSHandlerConstants.ADD_UT_ELEMENTS, securementUsernameTokenElements); - } - - /** - * Sets the web service specification settings. - *

- * The default settings follow the latest OASIS and changing anything might violate the OASIS specs. - * - * @param config web service security configuration or {@code null} to use default settings - */ - public void setWssConfig(WSSConfig config) { - securityEngine.setWssConfig(config); - wssConfig = config; - } - - /** - * Set whether to enable CRL checking or not when verifying trust in a certificate. - */ - public void setEnableRevocation(boolean enableRevocation) { - this.enableRevocation = enableRevocation; - } - - /** - * Set the WS-I Basic Security Profile compliance mode. Default is {@code true}. - */ - public void setBspCompliant(boolean bspCompliant) { - this.handler.setOption(WSHandlerConstants.IS_BSP_COMPLIANT, bspCompliant); - this.bspCompliant = bspCompliant; - } - - /** - * Sets the location of the SAML properties file. The file should be available on the classpath. - */ - public void setSamlProperties(String location) { - handler.setOption(WSHandlerConstants.SAML_PROP_FILE, location); - } - - /** - * Sets the time in seconds in the future within which the Created time of an - * incoming Timestamp is valid. The default is 60 seconds. - */ - public void setFutureTimeToLive(int futureTimeToLive) { - if (futureTimeToLive <= 0) { - throw new IllegalArgumentException("futureTimeToLive must be positive"); - } - this.futureTimeToLive = futureTimeToLive; - } - - /** - * Sets the SAML issuer. - */ - public void setSamlIssuer(SAMLIssuer samlIssuer) { - handler.setOption(WSHandlerConstants.SAML_PROP_REF_ID, SAML_ISSUER_PROPERTY_NAME); - this.samlIssuer = samlIssuer; - } - - public boolean getRemoveSecurityHeader() { - return removeSecurityHeader; - } - - public void setRemoveSecurityHeader(boolean removeSecurityHeader) { - this.removeSecurityHeader = removeSecurityHeader; - } - - @Override - public void afterPropertiesSet() throws Exception { - Assert.isTrue(validationActions != null || securementActions != null, - "validationActions or securementActions are required"); - if (validationActions != null) { - if ((validationAction & WSConstants.UT) != 0) { - Assert.notNull(validationCallbackHandler, "validationCallbackHandler is required"); - } - - if ((validationAction & WSConstants.SIGN) != 0) { - Assert.notNull(validationSignatureCrypto, "validationSignatureCrypto is required"); - } - } - // securement actions are not to be validated at start up as they could - // be configured dynamically via the message context - - // allow for qualified password types for .Net interoperability - securityEngine.getWssConfig().setAllowNamespaceQualifiedPasswordTypes(true); - securityEngine.getWssConfig().setWsiBSPCompliant(bspCompliant); - } - - @Override - protected void secureMessage(SoapMessage soapMessage, MessageContext messageContext) - throws WsSecuritySecurementException { - if (securementAction == WSConstants.NO_SECURITY && !enableSignatureConfirmation) { - return; - } - if (logger.isDebugEnabled()) { - logger.debug("Securing message [" + soapMessage + "] with actions [" + securementActions + "]"); - } - RequestData requestData = initializeRequestData(messageContext); - - Document envelopeAsDocument = soapMessage.getDocument(); - try { - // In case on signature confirmation with no other securement - // action, we need to pass an empty securementActionsVector to avoid - // NPE - if (securementAction == WSConstants.NO_SECURITY) { - securementActionsVector = new ArrayList(0); - } - - handler.doSenderAction(securementAction, envelopeAsDocument, requestData, securementActionsVector, false); - } - catch (WSSecurityException ex) { - throw new Wss4jSecuritySecurementException(ex.getMessage(), ex); - } - - soapMessage.setDocument(envelopeAsDocument); - } - - /** - * Creates and initializes a request data for the given message context. - * - * @param messageContext the message context - * @return the request data - */ - protected RequestData initializeRequestData(MessageContext messageContext) { - RequestData requestData = new RequestData(); - requestData.setMsgContext(messageContext); - - // reads securementUsername first from the context then from the property - String contextUsername = (String) messageContext.getProperty(SECUREMENT_USER_PROPERTY_NAME); - if (StringUtils.hasLength(contextUsername)) { - requestData.setUsername(contextUsername); - } - else { - requestData.setUsername(securementUsername); - } - - requestData.setTimeToLive(securementTimeToLive); - - requestData.setUseDerivedKey(securementUseDerivedKey); - - requestData.setWssConfig(wssConfig); - - messageContext.setProperty(WSHandlerConstants.TTL_TIMESTAMP, Integer.toString(securementTimeToLive)); - - messageContext.setProperty(SAML_ISSUER_PROPERTY_NAME, samlIssuer); - - return requestData; - } - - @Override - protected void validateMessage(SoapMessage soapMessage, MessageContext messageContext) - throws WsSecurityValidationException { - if (logger.isDebugEnabled()) { - logger.debug("Validating message [" + soapMessage + "] with actions [" + validationActions + "]"); - } - - if (validationAction == WSConstants.NO_SECURITY) { - return; - } - - Document envelopeAsDocument = soapMessage.getDocument(); - - // Header processing - - try { - List results = securityEngine - .processSecurityHeader(envelopeAsDocument, validationActor, validationCallbackHandler, - validationSignatureCrypto, validationDecryptionCrypto); - - // Results verification - if (CollectionUtils.isEmpty(results)) { - throw new Wss4jSecurityValidationException("No WS-Security header found"); - } - - checkResults(results, validationActionsVector); - - // puts the results in the context - // useful for Signature Confirmation - updateContextWithResults(messageContext, results); - - verifyCertificateTrust(results); - - verifyTimestamp(results); - - processPrincipal(results); - } - catch (WSSecurityException ex) { - throw new Wss4jSecurityValidationException(ex.getMessage(), ex); - } - - soapMessage.setDocument(envelopeAsDocument); - - if (this.getRemoveSecurityHeader()) { - soapMessage.getEnvelope().getHeader().removeHeaderElement(WS_SECURITY_NAME); - } - } - - /** - * Checks whether the received headers match the configured validation actions. Subclasses could override this method - * for custom verification behavior. - * - * - * @param results the results of the validation function - * @param validationActions the decoded validation actions - * @throws Wss4jSecurityValidationException if the results are deemed invalid - */ - protected void checkResults(List results, List validationActions) - throws Wss4jSecurityValidationException { - if (!handler.checkReceiverResultsAnyOrder(results, validationActions)) { - throw new Wss4jSecurityValidationException("Security processing failed (actions mismatch)"); - } - } - - /** - * Puts the results of WS-Security headers processing in the message context. Some actions like Signature - * Confirmation require this. - */ - @SuppressWarnings("unchecked") - private void updateContextWithResults(MessageContext messageContext, List results) { - List handlerResults; - if ((handlerResults = (List) messageContext.getProperty(WSHandlerConstants.RECV_RESULTS)) == null) { - handlerResults = new ArrayList(); - messageContext.setProperty(WSHandlerConstants.RECV_RESULTS, handlerResults); - } - WSHandlerResult rResult = new WSHandlerResult(validationActor, results); - handlerResults.add(0, rResult); - messageContext.setProperty(WSHandlerConstants.RECV_RESULTS, handlerResults); - } - - /** Verifies the trust of a certificate. */ - protected void verifyCertificateTrust(List results) throws WSSecurityException { - WSSecurityEngineResult actionResult = WSSecurityUtil.fetchActionResult(results, WSConstants.SIGN); - - if (actionResult != null) { - X509Certificate returnCert = - (X509Certificate) actionResult.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE); - Credential credential = new Credential(); - credential.setCertificates(new X509Certificate[] { returnCert}); - - RequestData requestData = new RequestData(); - requestData.setSigCrypto(validationSignatureCrypto); - requestData.setEnableRevocation(enableRevocation); - - SignatureTrustValidator validator = new SignatureTrustValidator(); - validator.validate(credential, requestData); - } - } - - /** Verifies the timestamp. */ - protected void verifyTimestamp(List results) throws WSSecurityException { - WSSecurityEngineResult actionResult = WSSecurityUtil.fetchActionResult(results, WSConstants.TS); - - if (actionResult != null) { - Timestamp timestamp = (Timestamp) actionResult.get(WSSecurityEngineResult.TAG_TIMESTAMP); - if (timestamp != null && timestampStrict) { - Credential credential = new Credential(); - credential.setTimestamp(timestamp); - - RequestData requestData = new RequestData(); - WSSConfig config = new WSSConfig(); - config.setTimeStampTTL(validationTimeToLive); - config.setTimeStampStrict(timestampStrict); - config.setTimeStampFutureTTL(futureTimeToLive); - requestData.setWssConfig(config); - - TimestampValidator validator = new TimestampValidator(); - validator.validate(credential, requestData); - } - } - } - - private void processPrincipal(List results) { - WSSecurityEngineResult actionResult = WSSecurityUtil.fetchActionResult(results, WSConstants.UT); - - if (actionResult != null) { - Principal principal = (Principal) actionResult.get(WSSecurityEngineResult.TAG_PRINCIPAL); - if (principal != null && principal instanceof WSUsernameTokenPrincipal) { - WSUsernameTokenPrincipal usernameTokenPrincipal = (WSUsernameTokenPrincipal) principal; - UsernameTokenPrincipalCallback callback = new UsernameTokenPrincipalCallback(usernameTokenPrincipal); - try { - validationCallbackHandler.handle(new Callback[]{callback}); - } - catch (IOException ex) { - logger.warn("Principal callback resulted in IOException", ex); - } - catch (UnsupportedCallbackException ex) { - // ignore - } - } - } - } - - @Override - protected void cleanUp() { - if (validationCallbackHandler != null) { - try { - CleanupCallback cleanupCallback = new CleanupCallback(); - validationCallbackHandler.handle(new Callback[]{cleanupCallback}); - } - catch (IOException ex) { - logger.warn("Cleanup callback resulted in IOException", ex); - } - catch (UnsupportedCallbackException ex) { - // ignore - } - } - } -} diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jSecuritySecurementException.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jSecuritySecurementException.java deleted file mode 100644 index 291c9cf0..00000000 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jSecuritySecurementException.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2005-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -import org.springframework.ws.soap.security.WsSecuritySecurementException; - -/** - * WSS4J-specific version of the {@link WsSecuritySecurementException}. - * - * @author Tareq Abed Rabbo - * @author Arjen Poutsma - * @since 1.5.0 - * @deprecated Transition to {@link org.springframework.ws.soap.security.wss4j2.Wss4jSecuritySecurementException} - */ -@SuppressWarnings("serial") -@Deprecated -public class Wss4jSecuritySecurementException extends WsSecuritySecurementException { - - public Wss4jSecuritySecurementException(String msg) { - super(msg); - } - - public Wss4jSecuritySecurementException(String msg, Throwable ex) { - super(msg, ex); - } - -} diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jSecurityValidationException.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jSecurityValidationException.java deleted file mode 100644 index ae10f2d0..00000000 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jSecurityValidationException.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2005-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -import org.springframework.ws.soap.security.WsSecurityValidationException; - -/** - * WSS4J-specific version of the {@link WsSecurityValidationException}. - * - * @author Tareq Abed Rabbo - * @author Arjen Poutsma - * @since 1.5.0 - * @deprecated Transition to {@link org.springframework.ws.soap.security.wss4j2.Wss4jSecurityValidationException} - */ -@SuppressWarnings("serial") -@Deprecated -public class Wss4jSecurityValidationException extends WsSecurityValidationException { - - public Wss4jSecurityValidationException(String msg) { - super(msg); - } - - public Wss4jSecurityValidationException(String msg, Throwable ex) { - super(msg, ex); - } - -} diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/AbstractWsPasswordCallbackHandler.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/AbstractWsPasswordCallbackHandler.java deleted file mode 100644 index f3de66bd..00000000 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/AbstractWsPasswordCallbackHandler.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright 2005-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j.callback; - -import java.io.IOException; -import javax.security.auth.callback.Callback; -import javax.security.auth.callback.UnsupportedCallbackException; - -import org.apache.ws.security.WSPasswordCallback; - -import org.springframework.ws.soap.security.callback.AbstractCallbackHandler; -import org.springframework.ws.soap.security.callback.CleanupCallback; - -/** - * Abstract base class for {@link javax.security.auth.callback.CallbackHandler} implementations that handle {@link - * WSPasswordCallback} callbacks. - * - * @author Arjen Poutsma - * @since 1.5.0 - * @deprecated Transition to {@link org.springframework.ws.soap.security.wss4j2.callback.AbstractWsPasswordCallbackHandler} - */ -@Deprecated -public abstract class AbstractWsPasswordCallbackHandler extends AbstractCallbackHandler { - - /** - * Handles {@link WSPasswordCallback} callbacks. Inspects the callback {@link WSPasswordCallback#getUsage() usage} - * code, and calls the various {@code handle*} template methods. - * - * @param callback the callback - * @throws IOException in case of I/O errors - * @throws UnsupportedCallbackException when the callback is not supported - */ - @Override - protected final void handleInternal(Callback callback) throws IOException, UnsupportedCallbackException { - if (callback instanceof WSPasswordCallback) { - WSPasswordCallback passwordCallback = (WSPasswordCallback) callback; - switch (passwordCallback.getUsage()) { - case WSPasswordCallback.DECRYPT: - handleDecrypt(passwordCallback); - break; - case WSPasswordCallback.USERNAME_TOKEN: - handleUsernameToken(passwordCallback); - break; - case WSPasswordCallback.SIGNATURE: - handleSignature(passwordCallback); - break; - case WSPasswordCallback.SECURITY_CONTEXT_TOKEN: - handleSecurityContextToken(passwordCallback); - break; - case WSPasswordCallback.CUSTOM_TOKEN: - handleCustomToken(passwordCallback); - break; - case WSPasswordCallback.SECRET_KEY: - handleSecretKey(passwordCallback); - break; - default: - throw new UnsupportedCallbackException(callback, - "Unknown usage [" + passwordCallback.getUsage() + "]"); - } - } - else if (callback instanceof CleanupCallback) { - handleCleanup((CleanupCallback) callback); - } - else if (callback instanceof UsernameTokenPrincipalCallback) { - handleUsernameTokenPrincipal((UsernameTokenPrincipalCallback) callback); - } - else { - throw new UnsupportedCallbackException(callback); - } - } - - /** - * Invoked when the callback has a {@link WSPasswordCallback#DECRYPT} usage. - * - *

This method is invoked when WSS4J needs a password to get the private key of the {@link - * WSPasswordCallback#getIdentifier() identifier} (username) from the keystore. WSS4J uses this private key to - * decrypt the session (symmetric) key. Because the encryption method uses the public key to encrypt the session key - * it needs no password (a public key is usually not protected by a password). - * - *

Default implementation throws an {@link UnsupportedCallbackException}. - */ - protected void handleDecrypt(WSPasswordCallback callback) throws IOException, UnsupportedCallbackException { - throw new UnsupportedCallbackException(callback); - } - - /** - * Invoked when the callback has a {@link WSPasswordCallback#USERNAME_TOKEN} usage. - * - *

This method is invoked when WSS4J needs the password to fill in or to verify a UsernameToken. - * - *

Default implementation throws an {@link UnsupportedCallbackException}. - */ - protected void handleUsernameToken(WSPasswordCallback callback) throws IOException, UnsupportedCallbackException { - throw new UnsupportedCallbackException(callback); - } - - /** - * Invoked when the callback has a {@link WSPasswordCallback#SIGNATURE} usage. - * - *

This method is invoked when WSS4J needs the password to get the private key of the {@link - * WSPasswordCallback#getIdentifier() identifier} (username) from the keystore. WSS4J uses this private key to - * produce a signature. The signature verfication uses the public key to verfiy the signature. - * - *

Default implementation throws an {@link UnsupportedCallbackException}. - */ - protected void handleSignature(WSPasswordCallback callback) throws IOException, UnsupportedCallbackException { - throw new UnsupportedCallbackException(callback); - } - - /** - * Invoked when the callback has a {@link WSPasswordCallback#SECURITY_CONTEXT_TOKEN} usage. - * - *

This method is invoked when WSS4J needs the key to to be associated with a SecurityContextToken. - * - *

Default implementation throws an {@link UnsupportedCallbackException}. - */ - protected void handleSecurityContextToken(WSPasswordCallback callback) - throws IOException, UnsupportedCallbackException { - throw new UnsupportedCallbackException(callback); - } - - /** - * Invoked when the callback has a {@link WSPasswordCallback#CUSTOM_TOKEN} usage. - * - *

Default implementation throws an {@link UnsupportedCallbackException}. - */ - protected void handleCustomToken(WSPasswordCallback callback) throws IOException, UnsupportedCallbackException { - throw new UnsupportedCallbackException(callback); - } - - /** - * Invoked when the callback has a {@link WSPasswordCallback#SECRET_KEY} usage. - * - *

Default implementation throws an {@link UnsupportedCallbackException}. - */ - protected void handleSecretKey(WSPasswordCallback callback) throws IOException, UnsupportedCallbackException { - throw new UnsupportedCallbackException(callback); - } - - /** - * Invoked when a {@link CleanupCallback} is passed to {@link #handle(Callback[])}. - * - *

Default implementation throws an {@link UnsupportedCallbackException}. - */ - protected void handleCleanup(CleanupCallback callback) throws IOException, UnsupportedCallbackException { - throw new UnsupportedCallbackException(callback); - } - - /** - * Invoked when a {@link UsernameTokenPrincipalCallback} is passed to {@link #handle(Callback[])}. - * - *

Default implementation throws an {@link UnsupportedCallbackException}. - */ - protected void handleUsernameTokenPrincipal(UsernameTokenPrincipalCallback callback) - throws IOException, UnsupportedCallbackException { - throw new UnsupportedCallbackException(callback); - } -} diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/KeyStoreCallbackHandler.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/KeyStoreCallbackHandler.java deleted file mode 100644 index 9ba9771a..00000000 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/KeyStoreCallbackHandler.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2005-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j.callback; - -import java.io.IOException; -import java.security.GeneralSecurityException; -import java.security.Key; -import java.security.KeyStore; -import javax.crypto.SecretKey; -import javax.security.auth.callback.UnsupportedCallbackException; - -import org.apache.ws.security.WSPasswordCallback; - -import org.springframework.beans.factory.InitializingBean; -import org.springframework.ws.soap.security.support.KeyStoreUtils; - -/** - * Callback handler that uses Java Security {@code KeyStore}s to handle cryptographic callbacks. Allows for - * specific key stores to be set for various cryptographic operations. - * - * @author Tareq Abed Rabbo - * @author Arjen Poutsma - * @see org.springframework.ws.soap.security.support.KeyStoreFactoryBean - * @since 1.5.0 - * @deprecated Transition to {@link org.springframework.ws.soap.security.wss4j2.callback.KeyStoreCallbackHandler} - */ -@Deprecated -public class KeyStoreCallbackHandler extends AbstractWsPasswordCallbackHandler implements InitializingBean { - - private String privateKeyPassword; - - private char[] symmetricKeyPassword; - - private KeyStore keyStore; - - /** Sets the key store to use if a symmetric key name is embedded. */ - public void setKeyStore(KeyStore keyStore) { - this.keyStore = keyStore; - } - - /** - * Sets the password used to retrieve private keys from the keystore. This property is required for decryption based - * on private keys, and signing. - */ - public void setPrivateKeyPassword(String privateKeyPassword) { - if (privateKeyPassword != null) { - this.privateKeyPassword = privateKeyPassword; - } - } - - /** - * Sets the password used to retrieve keys from the symmetric keystore. If this property is not set, it defaults to - * the private key password. - * - * @see #setPrivateKeyPassword(String) - */ - public void setSymmetricKeyPassword(String symmetricKeyPassword) { - if (symmetricKeyPassword != null) { - this.symmetricKeyPassword = symmetricKeyPassword.toCharArray(); - } - } - - @Override - public void afterPropertiesSet() throws Exception { - if (keyStore == null) { - loadDefaultKeyStore(); - } - if (symmetricKeyPassword == null) { - symmetricKeyPassword = privateKeyPassword.toCharArray(); - } - } - - @Override - protected void handleDecrypt(WSPasswordCallback callback) throws IOException, UnsupportedCallbackException { - callback.setPassword(privateKeyPassword); - } - - - @Override - protected void handleSecretKey(WSPasswordCallback callback) throws IOException, UnsupportedCallbackException { - try { - String identifier = callback.getIdentifier(); - Key key = keyStore.getKey(identifier, symmetricKeyPassword); - if (key instanceof SecretKey) { - callback.setKey(key.getEncoded()); - } - else { - logger.error("Key [" + key + "] is not a javax.crypto.SecretKey"); - } - } - catch (GeneralSecurityException ex) { - logger.error("Could not obtain symmetric key", ex); - } - } - - /** Loads the key store indicated by system properties. Delegates to {@link KeyStoreUtils#loadDefaultKeyStore()}. */ - protected void loadDefaultKeyStore() { - try { - keyStore = KeyStoreUtils.loadDefaultKeyStore(); - if (logger.isDebugEnabled()) { - logger.debug("Loaded default key store"); - } - } - catch (Exception ex) { - logger.warn("Could not open default key store", ex); - } - } - -} diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SimplePasswordValidationCallbackHandler.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SimplePasswordValidationCallbackHandler.java deleted file mode 100644 index 6a6e3b5e..00000000 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SimplePasswordValidationCallbackHandler.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2005-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j.callback; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; -import javax.security.auth.callback.UnsupportedCallbackException; - -import org.apache.ws.security.WSPasswordCallback; - -import org.springframework.beans.factory.InitializingBean; -import org.springframework.util.Assert; - -/** - * Simple callback handler that validates passwords against a in-memory {@code Properties} object. Password - * validation is done on a case-sensitive basis. - * - * @author Tareq Abed Rabbo - * @author Arjen Poutsma - * @see #setUsers(java.util.Properties) - * @since 1.5.0 - * @deprecated Transition to {@link org.springframework.ws.soap.security.wss4j2.callback.SimplePasswordValidationCallbackHandler} - */ -@Deprecated -public class SimplePasswordValidationCallbackHandler extends AbstractWsPasswordCallbackHandler - implements InitializingBean { - - private Map users = new HashMap(); - - /** Sets the users to validate against. Property names are usernames, property values are passwords. */ - public void setUsers(Properties users) { - for (Map.Entry entry : users.entrySet()) { - if (entry.getKey() instanceof String && entry.getValue() instanceof String) { - this.users.put((String) entry.getKey(), (String) entry.getValue()); - } - } - } - - public void setUsersMap(Map users) { - this.users = users; - } - - @Override - public void afterPropertiesSet() throws Exception { - Assert.notNull(users, "users is required"); - } - - @Override - protected void handleUsernameToken(WSPasswordCallback callback) throws IOException, UnsupportedCallbackException { - String identifier = callback.getIdentifier(); - callback.setPassword(users.get(identifier)); - } - -} \ No newline at end of file diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SpringSecurityPasswordValidationCallbackHandler.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SpringSecurityPasswordValidationCallbackHandler.java deleted file mode 100644 index 9ad660fb..00000000 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SpringSecurityPasswordValidationCallbackHandler.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2005-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j.callback; - -import java.io.IOException; -import javax.security.auth.callback.UnsupportedCallbackException; - -import org.apache.ws.security.WSPasswordCallback; -import org.apache.ws.security.WSUsernameTokenPrincipal; - -import org.springframework.beans.factory.InitializingBean; -import org.springframework.dao.DataAccessException; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.core.userdetails.UserCache; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.security.core.userdetails.cache.NullUserCache; -import org.springframework.util.Assert; -import org.springframework.ws.soap.security.callback.CleanupCallback; -import org.springframework.ws.soap.security.support.SpringSecurityUtils; - -/** - * Callback handler that validates a plain text or digest password using an Spring Security {@code UserDetailsService}. - * - *

An Spring Security {@link UserDetailsService} is used to load {@link UserDetails} from. The digest of the - * password contained in this details object is then compared with the digest in the message. - * - * @author Arjen Poutsma - * @since 2.1 - * @deprecated Transition to {@link org.springframework.ws.soap.security.wss4j2.callback.SpringSecurityPasswordValidationCallbackHandler} - */ -@Deprecated -public class SpringSecurityPasswordValidationCallbackHandler extends AbstractWsPasswordCallbackHandler - implements InitializingBean { - - private UserCache userCache = new NullUserCache(); - - private UserDetailsService userDetailsService; - - /** Sets the users cache. Not required, but can benefit performance. */ - public void setUserCache(UserCache userCache) { - this.userCache = userCache; - } - - /** Sets the Spring Security user details service. Required. */ - public void setUserDetailsService(UserDetailsService userDetailsService) { - this.userDetailsService = userDetailsService; - } - - @Override - public void afterPropertiesSet() throws Exception { - Assert.notNull(userDetailsService, "userDetailsService is required"); - } - - @Override - protected void handleUsernameToken(WSPasswordCallback callback) throws IOException, UnsupportedCallbackException { - String identifier = callback.getIdentifier(); - UserDetails user = loadUserDetails(identifier); - if (user != null) { - SpringSecurityUtils.checkUserValidity(user); - callback.setPassword(user.getPassword()); - } - } - - @Override - protected void handleUsernameTokenPrincipal(UsernameTokenPrincipalCallback callback) - throws IOException, UnsupportedCallbackException { - UserDetails user = loadUserDetails(callback.getPrincipal().getName()); - WSUsernameTokenPrincipal principal = callback.getPrincipal(); - UsernamePasswordAuthenticationToken authRequest = - new UsernamePasswordAuthenticationToken(principal, principal.getPassword(), user.getAuthorities()); - if (logger.isDebugEnabled()) { - logger.debug("Authentication success: " + authRequest.toString()); - } - SecurityContextHolder.getContext().setAuthentication(authRequest); - } - - @Override - protected void handleCleanup(CleanupCallback callback) throws IOException, UnsupportedCallbackException { - SecurityContextHolder.clearContext(); - } - - private UserDetails loadUserDetails(String username) throws DataAccessException { - UserDetails user = userCache.getUserFromCache(username); - - if (user == null) { - try { - user = userDetailsService.loadUserByUsername(username); - } - catch (UsernameNotFoundException notFound) { - if (logger.isDebugEnabled()) { - logger.debug("Username '" + username + "' not found"); - } - return null; - } - userCache.putUserInCache(user); - } - return user; - } -} diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/UsernameTokenPrincipalCallback.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/UsernameTokenPrincipalCallback.java deleted file mode 100644 index ecc753e4..00000000 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/UsernameTokenPrincipalCallback.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j.callback; - -import java.io.Serializable; -import javax.security.auth.callback.Callback; - -import org.apache.ws.security.WSUsernameTokenPrincipal; - -/** - * Underlying security services instantiate and pass a {@code UsernameTokenPrincipalCallback} to the - * {@code handle} method of a {@code CallbackHandler} to pass a security - * {@code WSUsernameTokenPrincipal}. - * - * @author Arjen Poutsma - * @see WSUsernameTokenPrincipal - * @since 1.5.0 - * @deprecated Transition to {@link org.springframework.ws.soap.security.wss4j2.callback.UsernameTokenPrincipalCallback} - */ -@Deprecated -public class UsernameTokenPrincipalCallback implements Callback, Serializable { - - private static final long serialVersionUID = -3022202225157082715L; - - private final WSUsernameTokenPrincipal principal; - - /** Construct a {@code UsernameTokenPrincipalCallback}. */ - public UsernameTokenPrincipalCallback(WSUsernameTokenPrincipal principal) { - this.principal = principal; - } - - /** Get the retrieved {@code Principal}. */ - public WSUsernameTokenPrincipal getPrincipal() { - return principal; - } -} diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/package.html b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/package.html deleted file mode 100644 index 1d1c4a69..00000000 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/package.html +++ /dev/null @@ -1,5 +0,0 @@ - - -Contains CallbackHandler implementations for WSS4J (deprecated as of Spring WS 2.3). - - \ No newline at end of file diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/package.html b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/package.html deleted file mode 100644 index add5a944..00000000 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/package.html +++ /dev/null @@ -1,6 +0,0 @@ - - -Contains classes for using the Apache WSS4J WS-Security implementation within -Spring-WS (deprecated as of Spring WS 2.3). - - \ No newline at end of file diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/support/CryptoFactoryBean.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/support/CryptoFactoryBean.java deleted file mode 100644 index c21220f3..00000000 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/support/CryptoFactoryBean.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright 2005-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j.support; - -import java.io.IOException; -import java.util.Properties; - -import org.apache.ws.security.components.crypto.Crypto; -import org.apache.ws.security.components.crypto.CryptoFactory; -import org.apache.ws.security.components.crypto.Merlin; - -import org.springframework.beans.factory.BeanClassLoaderAware; -import org.springframework.beans.factory.FactoryBean; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; -import org.springframework.util.Assert; - -/** - * Spring factory bean for a WSS4J {@link Crypto}. Allows for strong-typed property configuration, or configuration - * through {@link Properties}. - * - *

Requires either individual properties, or the {@link #setConfiguration(java.util.Properties) configuration} property - * to be set. - * - * @author Tareq Abed Rabbo - * @author Arjen Poutsma - * @see org.apache.ws.security.components.crypto.Crypto - * @since 1.5.0 - * @deprecated Transition to {@link org.springframework.ws.soap.security.wss4j2.support.CryptoFactoryBean} - */ -@Deprecated -public class CryptoFactoryBean implements FactoryBean, BeanClassLoaderAware, InitializingBean { - - private Properties configuration = new Properties(); - - private ClassLoader classLoader; - - private Crypto crypto; - - private static final String CRYPTO_PROVIDER_PROPERTY = "org.apache.ws.security.crypto.provider"; - - /** - * Sets the configuration of the Crypto. Setting this property overrides all previously set configuration, through - * the type-safe properties - * - * @see org.apache.ws.security.components.crypto.CryptoFactory#getInstance(java.util.Properties) - */ - public void setConfiguration(Properties properties) { - Assert.notNull(properties, "'properties' must not be null"); - this.configuration.putAll(properties); - } - - /** - * Sets the {@link org.apache.ws.security.components.crypto.Crypto} provider name. Defaults to {@link - * org.apache.ws.security.components.crypto.Merlin}. - * - *

This property maps to the WSS4J {@code org.apache.ws.security.crypto.provider} property. - * - * @param cryptoProviderClass the crypto provider class - */ - public void setCryptoProvider(Class cryptoProviderClass) { - this.configuration.setProperty(CRYPTO_PROVIDER_PROPERTY, cryptoProviderClass.getName()); - } - - /** - * Sets the location of the key store to be loaded in the {@link org.apache.ws.security.components.crypto.Crypto} - * instance. - * - *

This property maps to the WSS4J {@code org.apache.ws.security.crypto.merlin.file} property. - * - * @param location the key store location - * @throws java.io.IOException when the resource cannot be opened - */ - public void setKeyStoreLocation(Resource location) throws IOException { - String resourcePath = getResourcePath(location); - this.configuration.setProperty("org.apache.ws.security.crypto.merlin.file", resourcePath); - } - - private String getResourcePath(Resource resource) throws IOException { - try { - return resource.getFile().getAbsolutePath(); - } - catch (IOException ex) { - if (resource instanceof ClassPathResource) { - ClassPathResource classPathResource = (ClassPathResource) resource; - return classPathResource.getPath(); - } - else { - throw ex; - } - } - } - - /** - * Sets the key store provider. - * - *

This property maps to the WSS4J {@code org.apache.ws.security.crypto.merlin.keystore.provider} property. - * - * @param provider the key store provider - */ - public void setKeyStoreProvider(String provider) { - this.configuration.setProperty("org.apache.ws.security.crypto.merlin.keystore.provider", provider); - } - - /** - * Sets the key store password. Defaults to {@code security}. - * - *

This property maps to the WSS4J {@code org.apache.ws.security.crypto.merlin.keystore.password} property. - * - * @param password the key store password - */ - public void setKeyStorePassword(String password) { - this.configuration.setProperty("org.apache.ws.security.crypto.merlin.keystore.password", password); - } - - /** - * Sets the key store type. Defaults to {@link java.security.KeyStore#getDefaultType()}. - * - *

This property maps to the WSS4J {@code org.apache.ws.security.crypto.merlin.keystore.type} property. - * - * @param type the key store type - */ - public void setKeyStoreType(String type) { - this.configuration.setProperty("org.apache.ws.security.crypto.merlin.keystore.type", type); - } - - /** - * Sets the trust store password. Defaults to {@code changeit}. - * - *

WSS4J crypto uses the standard J2SE trust store, i.e. {@code $JAVA_HOME/lib/security/cacerts}. - * - *

This property maps to the WSS4J {@code org.apache.ws.security.crypto.merlin.cacerts.password} property. - * - * @param password the trust store password - */ - public void setTrustStorePassword(String password) { - this.configuration.setProperty("org.apache.ws.security.crypto.merlin.cacerts.password", password); - } - - /** - * Sets the alias name of the default certificate which has been specified as a property. This should be the - * certificate that is used for signature and encryption. This alias corresponds to the certificate that should be - * used whenever KeyInfo is not present in a signed or an encrypted message. - * - *

This property maps to the WSS4J {@code org.apache.ws.security.crypto.merlin.keystore.alias} property. - * - * @param defaultX509Alias alias name of the default X509 certificate - */ - public void setDefaultX509Alias(String defaultX509Alias) { - this.configuration.setProperty("org.apache.ws.security.crypto.merlin.keystore.alias", defaultX509Alias); - } - - @Override - public void setBeanClassLoader(ClassLoader classLoader) { - this.classLoader = classLoader; - } - - @Override - public void afterPropertiesSet() throws Exception { - if (!configuration.containsKey(CRYPTO_PROVIDER_PROPERTY)) { - configuration.setProperty(CRYPTO_PROVIDER_PROPERTY, Merlin.class.getName()); - } - this.crypto = CryptoFactory.getInstance(configuration, classLoader); - } - - @Override - public Class getObjectType() { - return Crypto.class; - } - - @Override - public boolean isSingleton() { - return true; - } - - @Override - public Crypto getObject() throws Exception { - return crypto; - } - -} diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/support/package.html b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/support/package.html deleted file mode 100644 index adc038ee..00000000 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j/support/package.html +++ /dev/null @@ -1,5 +0,0 @@ - - -Contains support classes for working with WSS4J (deprecated as of Spring WS 2.3). - - \ No newline at end of file diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jInterceptorTest.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jInterceptorTest.java deleted file mode 100644 index d346a541..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jInterceptorTest.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -public class AxiomWss4jInterceptorTest extends Wss4jInterceptorTestCase { - -} diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorEncryptionTest.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorEncryptionTest.java deleted file mode 100644 index 1812c97d..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorEncryptionTest.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -public class AxiomWss4jMessageInterceptorEncryptionTest extends Wss4jMessageInterceptorEncryptionTestCase { - -} diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorHeaderTest.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorHeaderTest.java deleted file mode 100644 index 370d801c..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorHeaderTest.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -public class AxiomWss4jMessageInterceptorHeaderTest extends Wss4jMessageInterceptorHeaderTestCase { - -} diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorSignTest.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorSignTest.java deleted file mode 100644 index 3bac8e5f..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorSignTest.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -public class AxiomWss4jMessageInterceptorSignTest extends Wss4jMessageInterceptorSignTestCase { - -} diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorSoapActionTest.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorSoapActionTest.java deleted file mode 100644 index 20539692..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorSoapActionTest.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -public class AxiomWss4jMessageInterceptorSoapActionTest extends Wss4jMessageInterceptorSoapActionTestCase { - -} diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorSpringSecurityCallbackHandlerTest.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorSpringSecurityCallbackHandlerTest.java deleted file mode 100644 index 5be3bb45..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorSpringSecurityCallbackHandlerTest.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -public class AxiomWss4jMessageInterceptorSpringSecurityCallbackHandlerTest - extends Wss4jMessageInterceptorSpringSecurityCallbackHandlerTestCase { - -} \ No newline at end of file diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorTimestampTest.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorTimestampTest.java deleted file mode 100644 index d5e23aa9..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorTimestampTest.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -public class AxiomWss4jMessageInterceptorTimestampTest extends Wss4jMessageInterceptorTimestampTestCase { - -} diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorUsernameTokenSignatureTest.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorUsernameTokenSignatureTest.java deleted file mode 100644 index f8e09df1..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorUsernameTokenSignatureTest.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -public class AxiomWss4jMessageInterceptorUsernameTokenSignatureTest - extends Wss4jMessageInterceptorUsernameTokenSignatureTestCase { - -} diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorUsernameTokenTest.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorUsernameTokenTest.java deleted file mode 100644 index 4162248d..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorUsernameTokenTest.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -public class AxiomWss4jMessageInterceptorUsernameTokenTest extends Wss4jMessageInterceptorUsernameTokenTestCase { - -} diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorX509Test.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorX509Test.java deleted file mode 100644 index 0b1bae09..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorX509Test.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -/** @author tareq */ -public class AxiomWss4jMessageInterceptorX509Test extends Wss4jMessageInterceptorX509TestCase { - -} diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jInterceptorTest.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jInterceptorTest.java deleted file mode 100644 index 7233fe9e..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jInterceptorTest.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -public class SaajWss4jInterceptorTest extends Wss4jInterceptorTestCase { - -} diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorEncryptionTest.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorEncryptionTest.java deleted file mode 100644 index 78b8cbf4..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorEncryptionTest.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -public class SaajWss4jMessageInterceptorEncryptionTest extends Wss4jMessageInterceptorEncryptionTestCase { - -} diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorHeaderTest.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorHeaderTest.java deleted file mode 100644 index 539313db..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorHeaderTest.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -public class SaajWss4jMessageInterceptorHeaderTest extends Wss4jMessageInterceptorHeaderTestCase { - -} diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorSignTest.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorSignTest.java deleted file mode 100644 index 4cbc1651..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorSignTest.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2005-2010 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.util.Iterator; -import javax.xml.namespace.QName; -import javax.xml.soap.MimeHeaders; -import javax.xml.soap.SOAPHeader; -import javax.xml.soap.SOAPHeaderElement; -import javax.xml.soap.SOAPMessage; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMResult; - -import org.springframework.ws.context.DefaultMessageContext; -import org.springframework.ws.context.MessageContext; -import org.springframework.ws.soap.SoapMessage; -import org.springframework.ws.soap.saaj.SaajSoapMessage; -import org.springframework.ws.soap.saaj.SaajSoapMessageFactory; -import org.springframework.xml.transform.StringSource; - -import org.junit.Test; - -import static org.junit.Assert.assertTrue; - -public class SaajWss4jMessageInterceptorSignTest extends Wss4jMessageInterceptorSignTestCase { - - private static final String PAYLOAD = - "QQQ"; - - @Test - public void testSignAndValidate() throws Exception { - Transformer transformer = TransformerFactory.newInstance().newTransformer(); - interceptor.setSecurementActions("Signature"); - interceptor.setEnableSignatureConfirmation(false); - interceptor.setSecurementPassword("123456"); - interceptor.setSecurementUsername("rsaKey"); - SOAPMessage saajMessage = saajSoap11MessageFactory.createMessage(); - transformer.transform(new StringSource(PAYLOAD), new DOMResult(saajMessage.getSOAPBody())); - SoapMessage message = new SaajSoapMessage(saajMessage, saajSoap11MessageFactory); - MessageContext messageContext = new DefaultMessageContext(message, new SaajSoapMessageFactory(saajSoap11MessageFactory)); - - interceptor.secureMessage(message, messageContext); - - SOAPHeader header = ((SaajSoapMessage) message).getSaajMessage().getSOAPHeader(); - Iterator iterator = header.getChildElements(new QName( - "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "Security")); - assertTrue("No security header", iterator.hasNext()); - SOAPHeaderElement securityHeader = (SOAPHeaderElement) iterator.next(); - iterator = securityHeader.getChildElements(new QName("http://www.w3.org/2000/09/xmldsig#", "Signature")); - assertTrue("No signature header", iterator.hasNext()); - - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - message.writeTo(bos); - - MimeHeaders mimeHeaders = new MimeHeaders(); - mimeHeaders.addHeader("Content-Type", "text/xml"); - ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); - - SOAPMessage signed = saajSoap11MessageFactory.createMessage(mimeHeaders, bis); - message = new SaajSoapMessage(signed, saajSoap11MessageFactory); - messageContext = new DefaultMessageContext(message, new SaajSoapMessageFactory(saajSoap11MessageFactory)); - - interceptor.validateMessage(message, messageContext); - } - -} diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorSoapActionTest.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorSoapActionTest.java deleted file mode 100644 index 21de82d5..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorSoapActionTest.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -public class SaajWss4jMessageInterceptorSoapActionTest extends Wss4jMessageInterceptorSoapActionTestCase { - -} diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorSpringSecurityCallbackHandlerTest.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorSpringSecurityCallbackHandlerTest.java deleted file mode 100644 index ed7faa1c..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorSpringSecurityCallbackHandlerTest.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -public class SaajWss4jMessageInterceptorSpringSecurityCallbackHandlerTest - extends Wss4jMessageInterceptorSpringSecurityCallbackHandlerTestCase { - -} \ No newline at end of file diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorTimestampTest.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorTimestampTest.java deleted file mode 100644 index 8e66b3ac..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorTimestampTest.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -public class SaajWss4jMessageInterceptorTimestampTest extends Wss4jMessageInterceptorTimestampTestCase { - -} diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorUsernameTokenSignatureTest.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorUsernameTokenSignatureTest.java deleted file mode 100644 index 6c31316c..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorUsernameTokenSignatureTest.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -public class SaajWss4jMessageInterceptorUsernameTokenSignatureTest - extends Wss4jMessageInterceptorUsernameTokenSignatureTestCase { - -} diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorUsernameTokenTest.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorUsernameTokenTest.java deleted file mode 100644 index 066d5b4a..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorUsernameTokenTest.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -public class SaajWss4jMessageInterceptorUsernameTokenTest extends Wss4jMessageInterceptorUsernameTokenTestCase { - -} diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorX509Test.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorX509Test.java deleted file mode 100644 index 3d4227c1..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorX509Test.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -/** @author tareq */ -public class SaajWss4jMessageInterceptorX509Test extends Wss4jMessageInterceptorX509TestCase { - -} diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jInterceptorTestCase.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jInterceptorTestCase.java deleted file mode 100644 index f602bc35..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jInterceptorTestCase.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2005-2010 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -import org.springframework.ws.context.DefaultMessageContext; -import org.springframework.ws.context.MessageContext; -import org.springframework.ws.soap.SoapMessage; -import org.springframework.ws.soap.security.WsSecuritySecurementException; -import org.springframework.ws.soap.security.WsSecurityValidationException; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -public abstract class Wss4jInterceptorTestCase extends Wss4jTestCase { - - @Test - public void testHandleRequest() throws Exception { - SoapMessage request = loadSoap11Message("empty-soap.xml"); - final Object requestMessage = getMessage(request); - SoapMessage validatedRequest = loadSoap11Message("empty-soap.xml"); - final Object validatedRequestMessage = getMessage(validatedRequest); - Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor() { - @Override - protected void secureMessage(SoapMessage soapMessage, MessageContext messageContext) - throws WsSecuritySecurementException { - fail("secure not expected"); - } - - @Override - protected void validateMessage(SoapMessage soapMessage, MessageContext messageContext) - throws WsSecurityValidationException { - assertEquals("Invalid message", requestMessage, getMessage(soapMessage)); - setMessage(soapMessage, validatedRequestMessage); - } - }; - MessageContext context = new DefaultMessageContext(request, getSoap11MessageFactory()); - interceptor.handleRequest(context, null); - assertEquals("Invalid request", validatedRequestMessage, getMessage((SoapMessage) context.getRequest())); - } - - @Test - public void testHandleResponse() throws Exception { - SoapMessage securedResponse = loadSoap11Message("empty-soap.xml"); - final Object securedResponseMessage = getMessage(securedResponse); - - Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor() { - - @Override - protected void secureMessage(SoapMessage soapMessage, MessageContext messageContext) - throws WsSecuritySecurementException { - setMessage(soapMessage, securedResponseMessage); - } - - @Override - protected void validateMessage(SoapMessage soapMessage, MessageContext messageContext) - throws WsSecurityValidationException { - fail("validate not expected"); - } - - }; - SoapMessage request = loadSoap11Message("empty-soap.xml"); - MessageContext context = new DefaultMessageContext(request, getSoap11MessageFactory()); - context.getResponse(); - interceptor.handleResponse(context, null); - assertEquals("Invalid response", securedResponseMessage, getMessage((SoapMessage) context.getResponse())); - } - -} diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorEncryptionTestCase.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorEncryptionTestCase.java deleted file mode 100644 index 60a9a969..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorEncryptionTestCase.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2005-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -import java.util.Properties; - -import org.junit.Test; -import org.w3c.dom.Document; - -import org.springframework.ws.context.DefaultMessageContext; -import org.springframework.ws.context.MessageContext; -import org.springframework.ws.soap.SoapMessage; -import org.springframework.ws.soap.security.wss4j.callback.KeyStoreCallbackHandler; -import org.springframework.ws.soap.security.wss4j.support.CryptoFactoryBean; - -public abstract class Wss4jMessageInterceptorEncryptionTestCase extends Wss4jTestCase { - - protected Wss4jSecurityInterceptor interceptor; - - @Override - protected void onSetup() throws Exception { - interceptor = new Wss4jSecurityInterceptor(); - interceptor.setValidationActions("Encrypt"); - interceptor.setSecurementActions("Encrypt"); - - KeyStoreCallbackHandler callbackHandler = new KeyStoreCallbackHandler(); - callbackHandler.setPrivateKeyPassword("123456"); - interceptor.setValidationCallbackHandler(callbackHandler); - - CryptoFactoryBean cryptoFactoryBean = new CryptoFactoryBean(); - - Properties cryptoFactoryBeanConfig = new Properties(); - cryptoFactoryBeanConfig.setProperty("org.apache.ws.security.crypto.provider", - "org.apache.ws.security.components.crypto.Merlin"); - cryptoFactoryBeanConfig.setProperty("org.apache.ws.security.crypto.merlin.keystore.type", "jceks"); - cryptoFactoryBeanConfig.setProperty("org.apache.ws.security.crypto.merlin.keystore.password", "123456"); - - // from the class path - cryptoFactoryBeanConfig.setProperty("org.apache.ws.security.crypto.merlin.file", "private.jks"); - cryptoFactoryBean.setConfiguration(cryptoFactoryBeanConfig); - cryptoFactoryBean.afterPropertiesSet(); - interceptor.setValidationDecryptionCrypto(cryptoFactoryBean - .getObject()); - interceptor.setSecurementEncryptionCrypto(cryptoFactoryBean - .getObject()); - - interceptor.afterPropertiesSet(); - } - - @Test - public void testDecryptRequest() throws Exception { - SoapMessage message = loadSoap11Message("encrypted-soap.xml"); - MessageContext messageContext = new DefaultMessageContext(message, getSoap11MessageFactory()); - interceptor.validateMessage(message, messageContext); - Document document = getDocument((SoapMessage) messageContext.getRequest()); - assertXpathEvaluatesTo("Decryption error", "Hello", "/SOAP-ENV:Envelope/SOAP-ENV:Body/echo:echoRequest/text()", - document); - assertXpathNotExists("Security Header not removed", "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security", - getDocument(message)); - } - - @Test - public void testEncryptResponse() throws Exception { - SoapMessage message = loadSoap11Message("empty-soap.xml"); - MessageContext messageContext = getSoap11MessageContext(message); - interceptor.setSecurementEncryptionUser("rsakey"); - interceptor.secureMessage(message, messageContext); - Document document = getDocument(message); - assertXpathExists("Encryption error", "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/xenc:EncryptedKey", - document); - } -} diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorHeaderTestCase.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorHeaderTestCase.java deleted file mode 100644 index 528dc3f0..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorHeaderTestCase.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright 2005-2010 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -import static org.junit.Assert.*; - -import java.io.ByteArrayOutputStream; -import java.util.Iterator; -import java.util.Properties; -import javax.xml.namespace.QName; - -import org.junit.Test; - -import org.springframework.ws.context.DefaultMessageContext; -import org.springframework.ws.context.MessageContext; -import org.springframework.ws.soap.SoapHeaderElement; -import org.springframework.ws.soap.SoapMessage; -import org.springframework.ws.soap.security.WsSecurityValidationException; -import org.springframework.ws.soap.security.wss4j.callback.SimplePasswordValidationCallbackHandler; - -/** - * @author Arjen Poutsma - * @author Tareq Abedrabbo - * @author Greg Turnquist - */ -public abstract class Wss4jMessageInterceptorHeaderTestCase extends Wss4jTestCase { - - private Wss4jSecurityInterceptor interceptor; - private Wss4jSecurityInterceptor interceptorThatKeepsSecurityHeader; - - @Override - protected void onSetup() throws Exception { - Properties users = new Properties(); - users.setProperty("Bert", "Ernie"); - interceptor = new Wss4jSecurityInterceptor(); - interceptor.setValidateRequest(true); - interceptor.setSecureResponse(true); - interceptor.setValidationActions("UsernameToken"); - SimplePasswordValidationCallbackHandler callbackHandler = new SimplePasswordValidationCallbackHandler(); - callbackHandler.setUsers(users); - interceptor.setValidationCallbackHandler(callbackHandler); - interceptor.afterPropertiesSet(); - - interceptorThatKeepsSecurityHeader = new Wss4jSecurityInterceptor(); - interceptorThatKeepsSecurityHeader.setValidateRequest(true); - interceptorThatKeepsSecurityHeader.setSecureResponse(true); - interceptorThatKeepsSecurityHeader.setValidationActions("UsernameToken"); - interceptorThatKeepsSecurityHeader.setValidationCallbackHandler(callbackHandler); - interceptorThatKeepsSecurityHeader.setRemoveSecurityHeader(false); - interceptorThatKeepsSecurityHeader.afterPropertiesSet(); - } - - @Test - public void testValidateUsernameTokenPlainText() throws Exception { - SoapMessage message = loadSoap11Message("usernameTokenPlainTextWithHeaders-soap.xml"); - MessageContext messageContext = new DefaultMessageContext(message, getSoap11MessageFactory()); - interceptor.validateMessage(message, messageContext); - Object result = getMessage(message); - assertNotNull("No result returned", result); - - for (Iterator i = message.getEnvelope().getHeader().examineAllHeaderElements(); i.hasNext();) { - SoapHeaderElement element = i.next(); - QName name = element.getName(); - if (name.getNamespaceURI() - .equals("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd")) { - fail("Security Header not removed"); - } - - } - - assertXpathNotExists("Security Header not removed", "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security", - getDocument(message)); - assertXpathExists("header1 not found", "/SOAP-ENV:Envelope/SOAP-ENV:Header/header1", getDocument(message)); - assertXpathExists("header2 not found", "/SOAP-ENV:Envelope/SOAP-ENV:Header/header2", getDocument(message)); - - } - - @Test - public void testValidateUsernameTokenPlainTextButKeepSecurityHeader() throws Exception { - SoapMessage message = loadSoap11Message("usernameTokenPlainTextWithHeaders-soap.xml"); - MessageContext messageContext = new DefaultMessageContext(message, getSoap11MessageFactory()); - interceptorThatKeepsSecurityHeader.validateMessage(message, messageContext); - Object result = getMessage(message); - assertNotNull("No result returned", result); - - boolean foundSecurityHeader = false; - for (Iterator i = message.getEnvelope().getHeader().examineAllHeaderElements(); i.hasNext();) { - SoapHeaderElement element = i.next(); - QName name = element.getName(); - if (name.getNamespaceURI() - .equals("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd")) { - foundSecurityHeader = true; - } - - } - assertTrue(foundSecurityHeader); - - assertXpathExists("header1 not found", "/SOAP-ENV:Envelope/SOAP-ENV:Header/header1", getDocument(message)); - assertXpathExists("header2 not found", "/SOAP-ENV:Envelope/SOAP-ENV:Header/header2", getDocument(message)); - - } - - @Test(expected=WsSecurityValidationException.class) - public void testEmptySecurityHeader() throws Exception { - SoapMessage message = loadSoap11Message("emptySecurityHeader-soap.xml"); - MessageContext messageContext = new DefaultMessageContext(message, getSoap11MessageFactory()); - interceptor.validateMessage(message, messageContext); - } - - @Test - public void testPreserveCustomHeaders() throws Exception { - interceptor.setSecurementActions("UsernameToken"); - interceptor.setSecurementUsername("Bert"); - interceptor.setSecurementPassword("Ernie"); - - ByteArrayOutputStream os = new ByteArrayOutputStream(); - SoapMessage message = loadSoap11Message("customHeader-soap.xml"); - MessageContext messageContext = new DefaultMessageContext(message, getSoap11MessageFactory()); - message.writeTo(os); - String document = os.toString("UTF-8"); - assertXpathEvaluatesTo("Header 1 does not exist", "test1", "/SOAP-ENV:Envelope/SOAP-ENV:Header/test:header1", - document); - assertXpathNotExists("Header 2 exist", "/SOAP-ENV:Envelope/SOAP-ENV:Header/test:header2", document); - - interceptor.secureMessage(message, messageContext); - - SoapHeaderElement element = message.getSoapHeader().addHeaderElement(new QName("http://test", "header2")); - element.setText("test2"); - - os = new ByteArrayOutputStream(); - message.writeTo(os); - document = os.toString("UTF-8"); - assertXpathEvaluatesTo("Header 1 does not exist", "test1", "/SOAP-ENV:Envelope/SOAP-ENV:Header/test:header1", - document); - assertXpathEvaluatesTo("Header 2 does not exist", "test2", "/SOAP-ENV:Envelope/SOAP-ENV:Header/test:header2", - document); - - os = new ByteArrayOutputStream(); - message.writeTo(os); - document = os.toString("UTF-8"); - assertXpathEvaluatesTo("Header 1 does not exist", "test1", "/SOAP-ENV:Envelope/SOAP-ENV:Header/test:header1", - document); - assertXpathEvaluatesTo("Header 2 does not exist", "test2", "/SOAP-ENV:Envelope/SOAP-ENV:Header/test:header2", - document); - } -} diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorSignTestCase.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorSignTestCase.java deleted file mode 100644 index 03a3e87d..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorSignTestCase.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2005-2010 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -import java.util.Properties; - -import org.springframework.ws.WebServiceMessage; -import org.springframework.ws.context.DefaultMessageContext; -import org.springframework.ws.context.MessageContext; -import org.springframework.ws.soap.SoapMessage; -import org.springframework.ws.soap.security.wss4j.support.CryptoFactoryBean; - -import org.junit.Test; -import org.w3c.dom.Document; - -import static org.junit.Assert.assertNotNull; - -public abstract class Wss4jMessageInterceptorSignTestCase extends Wss4jTestCase { - - protected Wss4jSecurityInterceptor interceptor; - - @Override - protected void onSetup() throws Exception { - interceptor = new Wss4jSecurityInterceptor(); - interceptor.setValidationActions("Signature"); - - CryptoFactoryBean cryptoFactoryBean = new CryptoFactoryBean(); - Properties cryptoFactoryBeanConfig = new Properties(); - cryptoFactoryBeanConfig.setProperty("org.apache.ws.security.crypto.provider", - "org.apache.ws.security.components.crypto.Merlin"); - cryptoFactoryBeanConfig.setProperty("org.apache.ws.security.crypto.merlin.keystore.type", "jceks"); - cryptoFactoryBeanConfig.setProperty("org.apache.ws.security.crypto.merlin.keystore.password", "123456"); - - // from the class path - cryptoFactoryBeanConfig.setProperty("org.apache.ws.security.crypto.merlin.file", "private.jks"); - cryptoFactoryBean.setConfiguration(cryptoFactoryBeanConfig); - cryptoFactoryBean.afterPropertiesSet(); - interceptor.setValidationSignatureCrypto(cryptoFactoryBean - .getObject()); - interceptor.setSecurementSignatureCrypto(cryptoFactoryBean - .getObject()); - interceptor.afterPropertiesSet(); - - } - - @Test - public void testValidateCertificate() throws Exception { - SoapMessage message = loadSoap11Message("signed-soap.xml"); - - MessageContext messageContext = new DefaultMessageContext(message, getSoap11MessageFactory()); - interceptor.validateMessage(message, messageContext); - Object result = getMessage(message); - assertNotNull("No result returned", result); - assertXpathNotExists("Security Header not removed", "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security", - getDocument(message)); - } - - @Test - public void testValidateCertificateWithSignatureConfirmation() throws Exception { - SoapMessage message = loadSoap11Message("signed-soap.xml"); - MessageContext messageContext = getSoap11MessageContext(message); - interceptor.setEnableSignatureConfirmation(true); - interceptor.validateMessage(message, messageContext); - WebServiceMessage response = messageContext.getResponse(); - interceptor.secureMessage(message, messageContext); - assertNotNull("No result returned", response); - Document document = getDocument((SoapMessage) response); - assertXpathExists("Absent SignatureConfirmation element", - "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/wsse11:SignatureConfirmation", document); - } - - @Test - public void testSignResponse() throws Exception { - interceptor.setSecurementActions("Signature"); - interceptor.setEnableSignatureConfirmation(false); - interceptor.setSecurementPassword("123456"); - interceptor.setSecurementUsername("rsaKey"); - SoapMessage message = loadSoap11Message("empty-soap.xml"); - MessageContext messageContext = getSoap11MessageContext(message); - - // interceptor.setSecurementSignatureKeyIdentifier("IssuerSerial"); - - interceptor.secureMessage(message, messageContext); - - Document document = getDocument(message); - assertXpathExists("Absent SignatureConfirmation element", - "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/ds:Signature", document); - - - } - - @Test - public void testSignResponseWithSignatureUser() throws Exception { - interceptor.setSecurementActions("Signature"); - interceptor.setEnableSignatureConfirmation(false); - interceptor.setSecurementPassword("123456"); - interceptor.setSecurementSignatureUser("rsaKey"); - SoapMessage message = loadSoap11Message("empty-soap.xml"); - MessageContext messageContext = getSoap11MessageContext(message); - - interceptor.secureMessage(message, messageContext); - - Document document = getDocument(message); - assertXpathExists("Absent SignatureConfirmation element", - "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/ds:Signature", document); - - - } -} diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorSoapActionTestCase.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorSoapActionTestCase.java deleted file mode 100644 index 836f2424..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorSoapActionTestCase.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2005-2010 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -import java.util.Properties; - -import org.springframework.ws.WebServiceMessageFactory; -import org.springframework.ws.context.DefaultMessageContext; -import org.springframework.ws.context.MessageContext; -import org.springframework.ws.soap.SoapMessage; -import org.springframework.ws.soap.security.wss4j.callback.SimplePasswordValidationCallbackHandler; - -import org.apache.ws.security.WSConstants; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -public abstract class Wss4jMessageInterceptorSoapActionTestCase extends Wss4jTestCase { - - private static final String SOAP_ACTION = "\"http://test\""; - - private Properties users; - - private Wss4jSecurityInterceptor interceptor; - - @Override - protected void onSetup() throws Exception { - users = new Properties(); - users.setProperty("Bert", "Ernie"); - interceptor = new Wss4jSecurityInterceptor(); - interceptor.setValidationActions("UsernameToken"); - interceptor.setSecurementActions("UsernameToken"); - interceptor.setSecurementPasswordType(WSConstants.PW_TEXT); - SimplePasswordValidationCallbackHandler callbackHandler = new SimplePasswordValidationCallbackHandler(); - callbackHandler.setUsers(users); - interceptor.setValidationCallbackHandler(callbackHandler); - - interceptor.afterPropertiesSet(); - } - - @Test - public void testPreserveSoapActionOnValidation() throws Exception { - SoapMessage message = loadSoap11Message("usernameTokenPlainText-soap.xml"); - message.setSoapAction(SOAP_ACTION); - MessageContext messageContext = new DefaultMessageContext(message, getSoap11MessageFactory()); - interceptor.validateMessage(message, messageContext); - - assertNotNull("Soap Action must not be null", message.getSoapAction()); - assertEquals("Soap Action is different from expected", SOAP_ACTION, message.getSoapAction()); - } - - @Test - public void testPreserveSoap12ActionOnValidation() throws Exception { - SoapMessage message = loadSoap12Message("usernameTokenPlainText-soap12.xml"); - message.setSoapAction(SOAP_ACTION); - WebServiceMessageFactory messageFactory = getSoap12MessageFactory(); - MessageContext messageContext = new DefaultMessageContext(message, messageFactory); - interceptor.validateMessage(message, messageContext); - - assertNotNull("Soap Action must not be null", message.getSoapAction()); - assertEquals("Soap Action is different from expected", SOAP_ACTION, message.getSoapAction()); - } - - @Test - public void testPreserveSoapActionOnSecurement() throws Exception { - SoapMessage message = loadSoap11Message("empty-soap.xml"); - message.setSoapAction(SOAP_ACTION); - interceptor.setSecurementUsername("Bert"); - interceptor.setSecurementPassword("Ernie"); - MessageContext messageContext = getSoap11MessageContext(message); - interceptor.secureMessage(message, messageContext); - - assertNotNull("Soap Action must not be null", message.getSoapAction()); - assertEquals("Soap Action is different from expected", SOAP_ACTION, message.getSoapAction()); - - } - - @Test - public void testPreserveSoap12ActionOnSecurement() throws Exception { - SoapMessage message = loadSoap12Message("empty-soap12.xml"); - message.setSoapAction(SOAP_ACTION); - interceptor.setSecurementUsername("Bert"); - interceptor.setSecurementPassword("Ernie"); - MessageContext messageContext = getSoap12MessageContext(message); - interceptor.secureMessage(message, messageContext); - - assertNotNull("Soap Action must not be null", message.getSoapAction()); - assertEquals("Soap Action is different from expected", SOAP_ACTION, message.getSoapAction()); - - } - - -} diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorSpringSecurityCallbackHandlerTestCase.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorSpringSecurityCallbackHandlerTestCase.java deleted file mode 100644 index 29efefa4..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorSpringSecurityCallbackHandlerTestCase.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright 2005-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -import java.util.Properties; - -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.provisioning.InMemoryUserDetailsManager; -import org.springframework.ws.context.DefaultMessageContext; -import org.springframework.ws.context.MessageContext; -import org.springframework.ws.server.EndpointInterceptor; -import org.springframework.ws.soap.SoapMessage; -import org.springframework.ws.soap.security.wss4j.callback.SpringSecurityPasswordValidationCallbackHandler; - -import org.apache.ws.security.WSConstants; -import org.junit.After; -import org.junit.Test; - -import static org.easymock.EasyMock.*; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -public abstract class Wss4jMessageInterceptorSpringSecurityCallbackHandlerTestCase extends Wss4jTestCase { - - private Properties users = new Properties(); - - private AuthenticationManager authenticationManager; - - @Override - protected void onSetup() throws Exception { - authenticationManager = createMock(AuthenticationManager.class); - users.setProperty("Bert", "Ernie,ROLE_TEST"); - } - - @After - public void tearDown() throws Exception { - verify(authenticationManager); - SecurityContextHolder.clearContext(); - } - - @Test - public void testValidateUsernameTokenPlainText() throws Exception { - EndpointInterceptor interceptor = prepareInterceptor("UsernameToken", true, false); - SoapMessage message = loadSoap11Message("usernameTokenPlainText-soap.xml"); - MessageContext messageContext = new DefaultMessageContext(message, getSoap11MessageFactory()); - interceptor.handleRequest(messageContext, null); - assertValidateUsernameToken(message); - - // test clean up - messageContext.getResponse(); - interceptor.handleResponse(messageContext, null); - interceptor.afterCompletion(messageContext, null, null); - assertNull("Authentication created", SecurityContextHolder.getContext().getAuthentication()); - } - - @Test - public void testValidateUsernameTokenDigest() throws Exception { - Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor(); - interceptor.setSecurementActions("UsernameToken"); - interceptor.setSecurementUsername("Bert"); - interceptor.setSecurementPassword("Ernie"); - interceptor.setSecurementPasswordType(WSConstants.PW_DIGEST); - - - SoapMessage message = loadSoap11Message("empty-soap.xml"); - MessageContext messageContext = new DefaultMessageContext(message, getSoap11MessageFactory()); - interceptor.handleRequest(messageContext); - - interceptor = prepareInterceptor("UsernameToken", true, true); - interceptor.handleRequest(messageContext, null); - assertValidateUsernameToken(message); - - // test clean up - messageContext.getResponse(); - interceptor.handleResponse(messageContext, null); - interceptor.afterCompletion(messageContext, null, null); - assertNull("Authentication created", SecurityContextHolder.getContext().getAuthentication()); - } - - protected void assertValidateUsernameToken(SoapMessage message) throws Exception { - Object result = getMessage(message); - assertNotNull("No result returned", result); - assertXpathNotExists("Security Header not removed", "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security", - getDocument(message)); - assertNotNull("No Authentication created", SecurityContextHolder.getContext().getAuthentication()); - } - - protected Wss4jSecurityInterceptor prepareInterceptor(String actions, boolean validating, boolean digest) - throws Exception { - Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor(); - if (validating) { - interceptor.setValidationActions(actions); - } - else { - interceptor.setSecurementActions(actions); - } - SpringSecurityPasswordValidationCallbackHandler callbackHandler = - new SpringSecurityPasswordValidationCallbackHandler(); - InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager(users); - callbackHandler.setUserDetailsService(userDetailsManager); - if (digest) { - interceptor.setSecurementPasswordType(WSConstants.PW_DIGEST); - } - else { - interceptor.setSecurementPasswordType(WSConstants.PW_TEXT); - } - interceptor.setValidationCallbackHandler(callbackHandler); - interceptor.afterPropertiesSet(); - replay(authenticationManager); - return interceptor; - } -} diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorTimestampTestCase.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorTimestampTestCase.java deleted file mode 100644 index 6f53b499..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorTimestampTestCase.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2005-2010 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; - -import org.springframework.ws.context.DefaultMessageContext; -import org.springframework.ws.context.MessageContext; -import org.springframework.ws.soap.SoapMessage; -import org.springframework.ws.soap.security.WsSecurityValidationException; - -import org.junit.Test; -import org.w3c.dom.Document; - -import static org.junit.Assert.assertEquals; - -public abstract class Wss4jMessageInterceptorTimestampTestCase extends Wss4jTestCase { - - @Test - public void testAddTimestamp() throws Exception { - Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor(); - interceptor.setSecurementActions("Timestamp"); - interceptor.afterPropertiesSet(); - SoapMessage message = loadSoap11Message("empty-soap.xml"); - MessageContext context = getSoap11MessageContext(message); - interceptor.secureMessage(message, context); - Document document = getDocument(message); - assertXpathExists("timestamp header not found", - "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/wsu:Timestamp", document); - } - - @Test - public void testValidateTimestamp() throws Exception { - Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor(); - interceptor.setValidationActions("Timestamp"); - interceptor.afterPropertiesSet(); - SoapMessage message = getMessageWithTimestamp(); - - MessageContext context = new DefaultMessageContext(message, getSoap11MessageFactory()); - interceptor.validateMessage(message, context); - assertXpathNotExists("Security Header not removed", "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security", - getDocument(message)); - } - - @Test(expected = WsSecurityValidationException.class) - public void testValidateTimestampWithExpiredTtl() throws Exception { - Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor(); - interceptor.setValidationActions("Timestamp"); - interceptor.afterPropertiesSet(); - SoapMessage message = loadSoap11Message("expiredTimestamp-soap.xml"); - MessageContext context = new DefaultMessageContext(message, getSoap11MessageFactory()); - interceptor.validateMessage(message, context); - } - - - @Test - public void testSecureTimestampWithCustomTtl() throws Exception { - Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor(); - interceptor.setSecurementActions("Timestamp"); - interceptor.setTimestampStrict(true); - int ttlInSeconds = 1; - interceptor.setSecurementTimeToLive(ttlInSeconds); - interceptor.afterPropertiesSet(); - SoapMessage message = loadSoap11Message("empty-soap.xml"); - MessageContext context = new DefaultMessageContext(message, getSoap11MessageFactory()); - interceptor.secureMessage(message, context); - - String created = xpathTemplate.evaluateAsString("/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/wsu:Timestamp/wsu:Created/text()", - message.getEnvelope().getSource()); - String expires = xpathTemplate.evaluateAsString("/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/wsu:Timestamp/wsu:Expires/text()", - message.getEnvelope().getSource()); - - DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SS'Z'"); - - long actualTtl = format.parse(expires).getTime() - format.parse(created).getTime(); - assertEquals("invalid ttl", 1000 * ttlInSeconds, actualTtl); - } - - private SoapMessage getMessageWithTimestamp() throws Exception { - Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor(); - interceptor.setSecurementActions("Timestamp"); - interceptor.afterPropertiesSet(); - SoapMessage message = loadSoap11Message("empty-soap.xml"); - MessageContext context = getSoap11MessageContext(message); - interceptor.secureMessage(message, context); - return message; - } -} diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorUsernameTokenSignatureTestCase.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorUsernameTokenSignatureTestCase.java deleted file mode 100644 index bb28b21e..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorUsernameTokenSignatureTestCase.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2005-2010 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -import org.springframework.ws.context.MessageContext; -import org.springframework.ws.soap.SoapMessage; - -import org.junit.Test; -import org.w3c.dom.Document; - -public abstract class Wss4jMessageInterceptorUsernameTokenSignatureTestCase extends Wss4jTestCase { - - @Test - public void testAddUsernameTokenSignature() throws Exception { - Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor(); - interceptor.setSecurementActions("UsernameTokenSignature"); - interceptor.setSecurementUsername("Bert"); - interceptor.setSecurementPassword("Ernie"); - interceptor.afterPropertiesSet(); - SoapMessage message = loadSoap11Message("empty-soap.xml"); - MessageContext context = getSoap11MessageContext(message); - interceptor.secureMessage(message, context); - - Document doc = getDocument(message); - assertXpathEvaluatesTo("Invalid Username", "Bert", - "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/wsse:UsernameToken/wsse:Username/text()", doc); - assertXpathExists("Invalid Password", - "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/wsse:UsernameToken/wsse:Password[@Type='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest']/text()", - doc); - } -} diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorUsernameTokenTestCase.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorUsernameTokenTestCase.java deleted file mode 100644 index ee77cb4c..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorUsernameTokenTestCase.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright 2005-2010 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -import java.util.Properties; - -import org.springframework.ws.context.DefaultMessageContext; -import org.springframework.ws.context.MessageContext; -import org.springframework.ws.soap.SoapMessage; -import org.springframework.ws.soap.security.wss4j.callback.SimplePasswordValidationCallbackHandler; - -import org.apache.ws.security.WSConstants; -import org.junit.Test; -import org.w3c.dom.Document; - -import static org.junit.Assert.assertNotNull; - -public abstract class Wss4jMessageInterceptorUsernameTokenTestCase extends Wss4jTestCase { - - private Properties users = new Properties(); - - @Override - protected void onSetup() throws Exception { - users.setProperty("Bert", "Ernie"); - } - - @Test - public void testValidateUsernameTokenPlainText() throws Exception { - Wss4jSecurityInterceptor interceptor = prepareInterceptor("UsernameToken", true, false); - SoapMessage message = loadSoap11Message("usernameTokenPlainText-soap.xml"); - MessageContext messageContext = new DefaultMessageContext(message, getSoap11MessageFactory()); - interceptor.validateMessage(message, messageContext); - assertValidateUsernameToken(message); - } - - @Test - public void testValidateUsernameTokenDigest() throws Exception { - Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor(); - interceptor.setSecurementActions("UsernameToken"); - interceptor.setSecurementUsername("Bert"); - interceptor.setSecurementPassword("Ernie"); - interceptor.setSecurementPasswordType(WSConstants.PW_DIGEST); - - SoapMessage message = loadSoap11Message("empty-soap.xml"); - MessageContext messageContext = new DefaultMessageContext(message, getSoap11MessageFactory()); - interceptor.handleRequest(messageContext); - - interceptor = prepareInterceptor("UsernameToken", true, true); - interceptor.validateMessage(message, messageContext); - assertValidateUsernameToken(message); - } - - @Test - public void testValidateUsernameTokenWithQualifiedType() throws Exception { - Wss4jSecurityInterceptor interceptor = prepareInterceptor("UsernameToken", true, false); - SoapMessage message = loadSoap11Message("usernameTokenPlainTextQualifiedType-soap.xml"); - MessageContext messageContext = new DefaultMessageContext(message, getSoap11MessageFactory()); - interceptor.validateMessage(message, messageContext); - assertValidateUsernameToken(message); - } - - @Test - public void testAddUsernameTokenPlainText() throws Exception { - Wss4jSecurityInterceptor interceptor = prepareInterceptor("UsernameToken", false, false); - interceptor.setSecurementUsername("Bert"); - interceptor.setSecurementPassword("Ernie"); - SoapMessage message = loadSoap11Message("empty-soap.xml"); - - MessageContext messageContext = getSoap11MessageContext(message); - - interceptor.secureMessage(message, messageContext); - assertAddUsernameTokenPlainText(message); - } - - @Test - public void testAddUsernameTokenDigest() throws Exception { - Wss4jSecurityInterceptor interceptor = prepareInterceptor("UsernameToken", false, true); - interceptor.setSecurementUsername("Bert"); - interceptor.setSecurementPassword("Ernie"); - SoapMessage message = loadSoap11Message("empty-soap.xml"); - - MessageContext messageContext = getSoap11MessageContext(message); - interceptor.secureMessage(message, messageContext); - assertAddUsernameTokenDigest(message); - } - - protected void assertValidateUsernameToken(SoapMessage message) throws Exception { - Object result = getMessage(message); - assertNotNull("No result returned", result); - assertXpathNotExists("Security Header not removed", "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security", - getDocument(message)); - } - - protected void assertAddUsernameTokenPlainText(SoapMessage message) throws Exception { - Object result = getMessage(message); - assertNotNull("No result returned", result); - Document doc = getDocument(message); - assertXpathEvaluatesTo("Invalid Username", "Bert", - "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/wsse:UsernameToken/wsse:Username/text()", doc); - assertXpathEvaluatesTo("Invalid Password", "Ernie", - "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/wsse:UsernameToken/wsse:Password[@Type='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText']/text()", - doc); - } - - protected void assertAddUsernameTokenDigest(SoapMessage message) throws Exception { - Object result = getMessage(message); - Document doc = getDocument(message); - assertNotNull("No result returned", result); - assertXpathEvaluatesTo("Invalid Username", "Bert", - "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/wsse:UsernameToken/wsse:Username/text()", doc); - assertXpathExists("Password does not exist", - "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/wsse:UsernameToken/wsse:Password[@Type='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest']", - doc); - - } - - protected Wss4jSecurityInterceptor prepareInterceptor(String actions, boolean validating, boolean digest) - throws Exception { - Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor(); - if (validating) { - interceptor.setValidationActions(actions); - } - else { - interceptor.setSecurementActions(actions); - } - SimplePasswordValidationCallbackHandler callbackHandler = new SimplePasswordValidationCallbackHandler(); - callbackHandler.setUsers(users); - if (digest) { - interceptor.setSecurementPasswordType(WSConstants.PW_DIGEST); - } - else { - interceptor.setSecurementPasswordType(WSConstants.PW_TEXT); - } - interceptor.setValidationCallbackHandler(callbackHandler); - - interceptor.setBspCompliant(false); - - interceptor.afterPropertiesSet(); - return interceptor; - } -} diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorX509TestCase.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorX509TestCase.java deleted file mode 100644 index 7d6b0cad..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorX509TestCase.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2005-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -import org.apache.ws.security.components.crypto.Merlin; -import org.junit.Test; -import org.w3c.dom.Document; - -import org.springframework.core.io.ClassPathResource; -import org.springframework.ws.context.MessageContext; -import org.springframework.ws.soap.SoapMessage; -import org.springframework.ws.soap.security.wss4j.support.CryptoFactoryBean; - -public abstract class Wss4jMessageInterceptorX509TestCase extends Wss4jTestCase { - - protected Wss4jSecurityInterceptor interceptor; - - @Override - protected void onSetup() throws Exception { - interceptor = new Wss4jSecurityInterceptor(); - interceptor.setSecurementActions("Signature"); - interceptor.setValidationActions("Signature"); - CryptoFactoryBean cryptoFactoryBean = new CryptoFactoryBean(); - cryptoFactoryBean.setCryptoProvider(Merlin.class); - cryptoFactoryBean.setKeyStoreType("jceks"); - cryptoFactoryBean.setKeyStorePassword("123456"); - cryptoFactoryBean.setKeyStoreLocation(new ClassPathResource("private.jks")); - - cryptoFactoryBean.afterPropertiesSet(); - interceptor.setSecurementSignatureCrypto(cryptoFactoryBean - .getObject()); - interceptor.setValidationSignatureCrypto(cryptoFactoryBean - .getObject()); - interceptor.afterPropertiesSet(); - - } - - @Test - public void testAddCertificate() throws Exception { - - interceptor.setSecurementPassword("123456"); - interceptor.setSecurementUsername("rsaKey"); - SoapMessage message = loadSoap11Message("empty-soap.xml"); - MessageContext messageContext = getSoap11MessageContext(message); - - interceptor.setSecurementSignatureKeyIdentifier("DirectReference"); - - interceptor.secureMessage(message, messageContext); - Document document = getDocument(message); - - assertXpathExists("Absent BinarySecurityToken element", - "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/wsse:BinarySecurityToken", document); - - // lets verify the signature that we've just generated - interceptor.validateMessage(message, messageContext); - } - -} diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jTestCase.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jTestCase.java deleted file mode 100644 index 5c9d826e..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jTestCase.java +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright 2005-2010 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j; - -import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; -import javax.xml.soap.MessageFactory; -import javax.xml.soap.MimeHeaders; -import javax.xml.soap.SOAPConstants; -import javax.xml.soap.SOAPMessage; -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamReader; -import javax.xml.transform.dom.DOMSource; - -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; -import org.springframework.ws.WebServiceMessage; -import org.springframework.ws.context.DefaultMessageContext; -import org.springframework.ws.context.MessageContext; -import org.springframework.ws.soap.SoapMessage; -import org.springframework.ws.soap.SoapMessageFactory; -import org.springframework.ws.soap.SoapVersion; -import org.springframework.ws.soap.axiom.AxiomSoapMessage; -import org.springframework.ws.soap.axiom.AxiomSoapMessageFactory; -import org.springframework.ws.soap.axiom.support.AxiomUtils; -import org.springframework.ws.soap.saaj.SaajSoapMessage; -import org.springframework.ws.soap.saaj.SaajSoapMessageFactory; -import org.springframework.xml.transform.StringSource; -import org.springframework.xml.xpath.Jaxp13XPathTemplate; - -import org.apache.axiom.soap.SOAP12Constants; -import org.apache.axiom.soap.impl.builder.StAXSOAPModelBuilder; -import org.junit.Assert; -import org.junit.Before; -import org.w3c.dom.Document; -import org.w3c.dom.Node; - -import static org.junit.Assert.assertTrue; - -public abstract class Wss4jTestCase { - - protected MessageFactory saajSoap11MessageFactory; - - protected MessageFactory saajSoap12MessageFactory; - - protected final boolean axiomTest = this.getClass().getSimpleName().startsWith("Axiom"); - - protected final boolean saajTest = this.getClass().getSimpleName().startsWith("Saaj"); - - protected Jaxp13XPathTemplate xpathTemplate = new Jaxp13XPathTemplate(); - - @Before - public final void setUp() throws Exception { - if (!axiomTest && !saajTest) { - throw new IllegalArgumentException("test class name must start with either Axiom or Saaj"); - } - saajSoap11MessageFactory = MessageFactory.newInstance(); - saajSoap12MessageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL); - Map namespaces = new HashMap(); - namespaces.put("SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"); - namespaces.put("wsse", - "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"); - namespaces.put("ds", "http://www.w3.org/2000/09/xmldsig#"); - namespaces.put("xenc", "http://www.w3.org/2001/04/xmlenc#"); - namespaces.put("wsse11", "http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd"); - namespaces.put("echo", "http://www.springframework.org/spring-ws/samples/echo"); - namespaces.put("wsu", - "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"); - namespaces.put("test", "http://test"); - xpathTemplate.setNamespaces(namespaces); - onSetup(); - } - - protected void assertXpathEvaluatesTo(String message, - String expectedValue, - String xpathExpression, - Document document) { - String actualValue = xpathTemplate.evaluateAsString(xpathExpression, new DOMSource(document)); - Assert.assertEquals(message, expectedValue, actualValue); - } - - protected void assertXpathEvaluatesTo(String message, - String expectedValue, - String xpathExpression, - String document) { - String actualValue = xpathTemplate.evaluateAsString(xpathExpression, new StringSource(document)); - Assert.assertEquals(message, expectedValue, actualValue); - } - - protected void assertXpathExists(String message, String xpathExpression, Document document) { - Node node = xpathTemplate.evaluateAsNode(xpathExpression, new DOMSource(document)); - Assert.assertNotNull(message, node); - } - - protected void assertXpathNotExists(String message, String xpathExpression, Document document) { - Node node = xpathTemplate.evaluateAsNode(xpathExpression, new DOMSource(document)); - Assert.assertNull(message, node); - } - - protected void assertXpathNotExists(String message, String xpathExpression, String document) { - Node node = xpathTemplate.evaluateAsNode(xpathExpression, new StringSource(document)); - Assert.assertNull(message, node); - } - - protected SaajSoapMessage loadSaaj11Message(String fileName) throws Exception { - MimeHeaders mimeHeaders = new MimeHeaders(); - mimeHeaders.addHeader("Content-Type", "text/xml"); - Resource resource = new ClassPathResource(fileName, getClass()); - InputStream is = resource.getInputStream(); - try { - assertTrue("Could not load SAAJ message [" + resource + "]", resource.exists()); - is = resource.getInputStream(); - return new SaajSoapMessage(saajSoap11MessageFactory.createMessage(mimeHeaders, is), saajSoap11MessageFactory); - } - finally { - is.close(); - } - } - - protected SaajSoapMessage loadSaaj12Message(String fileName) throws Exception { - MimeHeaders mimeHeaders = new MimeHeaders(); - mimeHeaders.addHeader("Content-Type", "application/soap+xml"); - Resource resource = new ClassPathResource(fileName, getClass()); - InputStream is = resource.getInputStream(); - try { - assertTrue("Could not load SAAJ message [" + resource + "]", resource.exists()); - is = resource.getInputStream(); - return new SaajSoapMessage(saajSoap12MessageFactory.createMessage(mimeHeaders, is), saajSoap12MessageFactory); - } - finally { - is.close(); - } - } - - protected AxiomSoapMessage loadAxiom11Message(String fileName) throws Exception { - Resource resource = new ClassPathResource(fileName, getClass()); - InputStream is = resource.getInputStream(); - try { - assertTrue("Could not load Axiom message [" + resource + "]", resource.exists()); - is = resource.getInputStream(); - - XMLStreamReader parser = XMLInputFactory.newInstance().createXMLStreamReader(is); - StAXSOAPModelBuilder builder = new StAXSOAPModelBuilder(parser, null); - org.apache.axiom.soap.SOAPMessage soapMessage = builder.getSoapMessage(); - return new AxiomSoapMessage(soapMessage, "", true, true); - } - finally { - is.close(); - } - } - - @SuppressWarnings("Since15") - protected AxiomSoapMessage loadAxiom12Message(String fileName) throws Exception { - Resource resource = new ClassPathResource(fileName, getClass()); - InputStream is = resource.getInputStream(); - try { - assertTrue("Could not load Axiom message [" + resource + "]", resource.exists()); - is = resource.getInputStream(); - - XMLStreamReader parser = XMLInputFactory.newInstance().createXMLStreamReader(is); - StAXSOAPModelBuilder builder = new StAXSOAPModelBuilder(parser, SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI); - org.apache.axiom.soap.SOAPMessage soapMessage = builder.getSoapMessage(); - return new AxiomSoapMessage(soapMessage, "", true, true); - } - finally { - is.close(); - } - } - - protected Object getMessage(SoapMessage soapMessage) { - if (soapMessage instanceof SaajSoapMessage) { - return ((SaajSoapMessage) soapMessage).getSaajMessage(); - } - if (soapMessage instanceof AxiomSoapMessage) { - return ((AxiomSoapMessage) soapMessage).getAxiomMessage(); - - } - throw new IllegalArgumentException("Illegal message: " + soapMessage); - } - - protected void setMessage(SoapMessage soapMessage, Object message) { - if (soapMessage instanceof SaajSoapMessage) { - ((SaajSoapMessage) soapMessage).setSaajMessage((SOAPMessage) message); - return; - } - if (soapMessage instanceof AxiomSoapMessage) { - ((AxiomSoapMessage) soapMessage).setAxiomMessage((org.apache.axiom.soap.SOAPMessage) message); - return; - } - throw new IllegalArgumentException("Illegal message: " + message); - } - - protected void onSetup() throws Exception { - } - - protected SoapMessage loadSoap11Message(String fileName) throws Exception { - if (axiomTest) { - return loadAxiom11Message(fileName); - } - if (saajTest) { - return loadSaaj11Message(fileName); - } - throw new IllegalArgumentException(); - } - - protected SoapMessage loadSoap12Message(String fileName) throws Exception { - if (axiomTest) { - return loadAxiom12Message(fileName); - } - if (saajTest) { - return loadSaaj12Message(fileName); - } - throw new IllegalArgumentException(); - } - - protected SoapMessageFactory getSoap11MessageFactory() throws Exception { - if (axiomTest) { - return new AxiomSoapMessageFactory(); - } - if (saajTest) { - return new SaajSoapMessageFactory(saajSoap11MessageFactory); - } - throw new IllegalArgumentException(); - } - - protected SoapMessageFactory getSoap12MessageFactory() throws Exception { - SoapMessageFactory messageFactory; - if (axiomTest) { - messageFactory = new AxiomSoapMessageFactory(); - } else if (saajTest) { - messageFactory = new SaajSoapMessageFactory(saajSoap12MessageFactory); - } else - throw new IllegalArgumentException(); - messageFactory.setSoapVersion(SoapVersion.SOAP_12); - return messageFactory; - } - - protected Document getDocument(SoapMessage message) throws Exception { - if (axiomTest) { - return AxiomUtils.toDocument(((AxiomSoapMessage) message).getAxiomMessage().getSOAPEnvelope()); - } - if (saajTest) { - return ((SaajSoapMessage) message).getSaajMessage().getSOAPPart(); - } - throw new IllegalArgumentException(); - } - - protected MessageContext getSoap11MessageContext(final SoapMessage response) throws Exception { - return new DefaultMessageContext(response, getSoap11MessageFactory()) { - @Override - public WebServiceMessage getResponse() { - return response; - } - }; - } - - protected MessageContext getSoap12MessageContext(final SoapMessage response) throws Exception { - return new DefaultMessageContext(response, getSoap12MessageFactory()) { - @Override - public WebServiceMessage getResponse() { - return response; - } - }; - } - -} diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/callback/KeyStoreCallbackHandlerTest.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/callback/KeyStoreCallbackHandlerTest.java deleted file mode 100644 index ca725eff..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/callback/KeyStoreCallbackHandlerTest.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2005-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j.callback; - -import java.security.KeyStore; - -import org.springframework.core.io.ClassPathResource; -import org.springframework.ws.soap.security.support.KeyStoreFactoryBean; - -import org.apache.ws.security.WSPasswordCallback; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -public class KeyStoreCallbackHandlerTest { - - private KeyStoreCallbackHandler callbackHandler; - - private WSPasswordCallback callback; - - @Before - public void setUp() throws Exception { - callbackHandler = new KeyStoreCallbackHandler(); - callback = new WSPasswordCallback("secretkey", WSPasswordCallback.SECRET_KEY); - - KeyStoreFactoryBean factory = new KeyStoreFactoryBean(); - factory.setLocation(new ClassPathResource("private.jks")); - factory.setPassword("123456"); - factory.setType("JCEKS"); - factory.afterPropertiesSet(); - KeyStore keyStore = factory.getObject(); - callbackHandler.setKeyStore(keyStore); - callbackHandler.setSymmetricKeyPassword("123456"); - } - - @Test - public void testHandleKeyName() throws Exception { - callbackHandler.handleInternal(callback); - Assert.assertNotNull("symmetric key must not be null", callback.getKey()); - } - -} diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/callback/SpringSecurityPasswordValidationCallbackHandlerTest.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/callback/SpringSecurityPasswordValidationCallbackHandlerTest.java deleted file mode 100644 index 41b1cea2..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/callback/SpringSecurityPasswordValidationCallbackHandlerTest.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2005-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j.callback; - -import java.util.Collection; -import java.util.Collections; - -import org.springframework.security.core.Authentication; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.core.context.SecurityContext; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.core.userdetails.User; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; - -import org.apache.ws.security.WSUsernameTokenPrincipal; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import static org.easymock.EasyMock.*; - -/** @author tareq */ -public class SpringSecurityPasswordValidationCallbackHandlerTest { - - private SpringSecurityPasswordValidationCallbackHandler callbackHandler; - - private SimpleGrantedAuthority grantedAuthority; - - private UsernameTokenPrincipalCallback callback; - - private UserDetails user; - - @Before - public void setUp() throws Exception { - callbackHandler = new SpringSecurityPasswordValidationCallbackHandler(); - - grantedAuthority = new SimpleGrantedAuthority("ROLE_1"); - user = new User("Ernie", "Bert", true, true, true, true, Collections.singleton(grantedAuthority)); - - WSUsernameTokenPrincipal principal = new WSUsernameTokenPrincipal("Ernie", true); - callback = new UsernameTokenPrincipalCallback(principal); - } - - @Test - public void testHandleUsernameTokenPrincipal() throws Exception { - UserDetailsService userDetailsService = createMock(UserDetailsService.class); - callbackHandler.setUserDetailsService(userDetailsService); - - expect(userDetailsService.loadUserByUsername("Ernie")).andReturn(user).anyTimes(); - - replay(userDetailsService); - - callbackHandler.handleUsernameTokenPrincipal(callback); - SecurityContext context = SecurityContextHolder.getContext(); - Assert.assertNotNull("SecurityContext must not be null", context); - Authentication authentication = context.getAuthentication(); - Assert.assertNotNull("Authentication must not be null", authentication); - Collection authorities = authentication.getAuthorities(); - Assert.assertTrue("GrantedAuthority[] must not be null or empty", - (authorities != null && authorities.size() > 0)); - Assert.assertEquals("Unexpected authority", grantedAuthority, authorities.iterator().next()); - - verify(userDetailsService); - } -} diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/support/CryptoFactoryBeanTest.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/support/CryptoFactoryBeanTest.java deleted file mode 100644 index ba8ca390..00000000 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j/support/CryptoFactoryBeanTest.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2005-2010 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 org.springframework.ws.soap.security.wss4j.support; - -import java.util.Properties; - -import org.springframework.core.io.ClassPathResource; -import org.springframework.util.ClassUtils; - -import org.apache.ws.security.components.crypto.Merlin; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -public class CryptoFactoryBeanTest { - - private CryptoFactoryBean factoryBean; - - @Before - public void setUp() throws Exception { - factoryBean = new CryptoFactoryBean(); - } - - @Test - public void testSetConfiguration() throws Exception { - Properties configuration = new Properties(); - configuration.setProperty("org.apache.ws.security.crypto.provider", - "org.apache.ws.security.components.crypto.Merlin"); - configuration.setProperty("org.apache.ws.security.crypto.merlin.keystore.type", "jceks"); - configuration.setProperty("org.apache.ws.security.crypto.merlin.keystore.password", "123456"); - configuration.setProperty("org.apache.ws.security.crypto.merlin.file", "private.jks"); - - factoryBean.setConfiguration(configuration); - factoryBean.setBeanClassLoader(ClassUtils.getDefaultClassLoader()); - factoryBean.afterPropertiesSet(); - - Object result = factoryBean.getObject(); - Assert.assertNotNull("No result", result); - Assert.assertTrue("Not a Merlin instance", result instanceof Merlin); - } - - @Test - public void testProperties() throws Exception { - factoryBean.setKeyStoreType("jceks"); - factoryBean.setKeyStorePassword("123456"); - factoryBean.setKeyStoreLocation(new ClassPathResource("private.jks")); - factoryBean.setBeanClassLoader(ClassUtils.getDefaultClassLoader()); - factoryBean.afterPropertiesSet(); - Object result = factoryBean.getObject(); - Assert.assertNotNull("No result", result); - Assert.assertTrue("Not a Merlin instance", result instanceof Merlin); - } -} \ No newline at end of file diff --git a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j2/Wss4jTestCase.java b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j2/Wss4jTestCase.java index 2bdeeee2..9c0d7221 100644 --- a/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j2/Wss4jTestCase.java +++ b/spring-ws-security/src/test/java/org/springframework/ws/soap/security/wss4j2/Wss4jTestCase.java @@ -27,6 +27,13 @@ import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamReader; import javax.xml.transform.dom.DOMSource; +import org.apache.axiom.soap.SOAP12Constants; +import org.apache.axiom.soap.impl.builder.StAXSOAPModelBuilder; +import org.junit.Assert; +import org.junit.Before; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.ws.WebServiceMessage; @@ -43,14 +50,7 @@ import org.springframework.ws.soap.saaj.SaajSoapMessageFactory; import org.springframework.xml.transform.StringSource; import org.springframework.xml.xpath.Jaxp13XPathTemplate; -import org.apache.axiom.soap.SOAP12Constants; -import org.apache.axiom.soap.impl.builder.StAXSOAPModelBuilder; -import org.junit.Assert; -import org.junit.Before; -import org.w3c.dom.Document; -import org.w3c.dom.Node; - -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; public abstract class Wss4jTestCase { diff --git a/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/XmppMessageReceiver.java b/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/XmppMessageReceiver.java index 5b967dde..a04f4587 100644 --- a/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/XmppMessageReceiver.java +++ b/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/XmppMessageReceiver.java @@ -64,7 +64,11 @@ public class XmppMessageReceiver extends AbstractStandaloneMessageReceiver { @Override protected void onActivate() throws XMPPException, IOException, SmackException { if (!connection.isConnected()) { - connection.connect(); + try { + connection.connect(); + } catch (InterruptedException e) { + throw new IOException(e); + } } } @@ -100,7 +104,7 @@ public class XmppMessageReceiver extends AbstractStandaloneMessageReceiver { private class WebServicePacketListener implements StanzaListener { @Override - public void processPacket(Stanza packet) { + public void processStanza(Stanza packet) { logger.info("Received " + packet); if (packet instanceof Message) { Message message = (Message) packet; diff --git a/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/XmppReceiverConnection.java b/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/XmppReceiverConnection.java index 578ef85e..747aaedf 100644 --- a/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/XmppReceiverConnection.java +++ b/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/XmppReceiverConnection.java @@ -145,6 +145,8 @@ public class XmppReceiverConnection extends AbstractReceiverConnection { connection.sendStanza(responseMessage); } catch (SmackException.NotConnectedException e) { throw new IOException(e); + } catch (InterruptedException e) { + throw new IOException(e); } } } diff --git a/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/XmppSenderConnection.java b/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/XmppSenderConnection.java index 37d2efdb..ab946889 100644 --- a/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/XmppSenderConnection.java +++ b/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/XmppSenderConnection.java @@ -23,8 +23,8 @@ import java.net.URI; import java.net.URISyntaxException; import java.util.Iterator; -import org.jivesoftware.smack.PacketCollector; import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.StanzaCollector; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.filter.AndFilter; import org.jivesoftware.smack.filter.StanzaFilter; @@ -32,6 +32,8 @@ import org.jivesoftware.smack.filter.StanzaTypeFilter; import org.jivesoftware.smack.filter.ThreadFilter; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Stanza; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.stringprep.XmppStringprepException; import org.springframework.util.Assert; import org.springframework.ws.WebServiceMessage; @@ -64,7 +66,11 @@ public class XmppSenderConnection extends AbstractSenderConnection { Assert.hasLength(to, "'to' must not be empty"); Assert.hasLength(thread, "'thread' must not be empty"); this.connection = connection; - this.requestMessage = new Message(to, Message.Type.chat); + try { + this.requestMessage = new Message(JidCreate.from(to), Message.Type.chat); + } catch (XmppStringprepException e) { + throw new RuntimeException(e); + } this.requestMessage.setThread(thread); } @@ -134,6 +140,8 @@ public class XmppSenderConnection extends AbstractSenderConnection { connection.sendStanza(requestMessage); } catch (SmackException.NotConnectedException e) { throw new IOException(e); + } catch (InterruptedException e) { + throw new IOException(e); } } @@ -145,14 +153,17 @@ public class XmppSenderConnection extends AbstractSenderConnection { protected void onReceiveBeforeRead() throws IOException { StanzaFilter packetFilter = createPacketFilter(); - PacketCollector collector = connection.createPacketCollector(packetFilter); - Stanza packet = receiveTimeout >= 0 ? collector.nextResult(receiveTimeout) : collector.nextResult(); - if (packet instanceof Message) { - responseMessage = (Message) packet; - } - else if (packet != null) { - throw new IllegalArgumentException( - "Wrong packet type: [" + packet.getClass() + "]. Only Messages can be handled."); + StanzaCollector collector = connection.createStanzaCollector(packetFilter); + try { + Stanza packet = receiveTimeout >= 0 ? collector.nextResult(receiveTimeout) : collector.nextResult(); + if (packet instanceof Message) { + responseMessage = (Message) packet; + } else if (packet != null) { + throw new IllegalArgumentException( + "Wrong packet type: [" + packet.getClass() + "]. Only Messages can be handled."); + } + } catch (InterruptedException e) { + throw new IOException(e); } } diff --git a/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/support/XmppConnectionFactoryBean.java b/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/support/XmppConnectionFactoryBean.java index 83da23f0..de59b080 100644 --- a/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/support/XmppConnectionFactoryBean.java +++ b/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/support/XmppConnectionFactoryBean.java @@ -22,6 +22,8 @@ import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.tcp.XMPPTCPConnection; import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration; +import org.jxmpp.jid.parts.Resourcepart; +import org.jxmpp.stringprep.XmppStringprepException; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.FactoryBean; @@ -94,12 +96,15 @@ public class XmppConnectionFactoryBean implements FactoryBean Assert.hasText(password, "'password' must not be empty"); connection = new XMPPTCPConnection(configuration); - connection.connect(); - if (StringUtils.hasText(resource)) { - connection.login(username, password, resource); - } - else { - connection.login(username, password); + try { + connection.connect(); + if (StringUtils.hasText(resource)) { + connection.login(username, password, Resourcepart.from(resource)); + } else { + connection.login(username, password); + } + } catch (InterruptedException e) { + throw new IOException(e); } } @@ -130,13 +135,13 @@ public class XmppConnectionFactoryBean implements FactoryBean * @param port the port to connect to * @param serviceName the name of the service to connect to. May be {@code null} */ - protected XMPPTCPConnectionConfiguration createConnectionConfiguration(String host, int port, String serviceName) { + protected XMPPTCPConnectionConfiguration createConnectionConfiguration(String host, int port, String serviceName) throws XmppStringprepException { Assert.hasText(host, "'host' must not be empty"); if (StringUtils.hasText(serviceName)) { return XMPPTCPConnectionConfiguration.builder() .setHost(host) .setPort(port) - .setServiceName(serviceName) + .setXmppDomain(serviceName) .build(); } else { diff --git a/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/support/XmppTransportUtils.java b/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/support/XmppTransportUtils.java index 8935ea3d..2e113ad3 100644 --- a/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/support/XmppTransportUtils.java +++ b/spring-ws-support/src/main/java/org/springframework/ws/transport/xmpp/support/XmppTransportUtils.java @@ -42,7 +42,8 @@ public abstract class XmppTransportUtils { * Converts the given XMPP destination into a {@code xmpp} URI. */ public static URI toUri(Message requestMessage) throws URISyntaxException { - return new URI(XmppTransportConstants.XMPP_URI_SCHEME, requestMessage.getTo(), null); + return new URI(XmppTransportConstants.XMPP_URI_SCHEME, + requestMessage.getTo().asDomainFullJidIfPossible().asUnescapedString(), null); } public static String getTo(URI uri) { diff --git a/spring4-next-profile.gradle b/spring4-next-profile.gradle deleted file mode 100644 index 3327151f..00000000 --- a/spring4-next-profile.gradle +++ /dev/null @@ -1,6 +0,0 @@ -/** - * Enable with "-Pprofile=spring4-next" - */ - -ext.springVersion = "4.3.10.RELEASE" -ext.springSecurityVersion = "4.2.3.RELEASE" \ No newline at end of file diff --git a/spring5-profile.gradle b/spring5-profile.gradle deleted file mode 100644 index 316447d2..00000000 --- a/spring5-profile.gradle +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Enable with "-Pprofile=spring5" - */ - -ext.springVersion = "5.0.0.BUILD-SNAPSHOT" -ext.springSecurityVersion = "4.2.4.BUILD-SNAPSHOT" - -compileJava { - sourceCompatibility=1.8 - targetCompatibility=1.8 -} - -repositories { - maven { url 'https://repo.spring.io/libs-snapshot' } -} diff --git a/springnext-profile.gradle b/springnext-profile.gradle new file mode 100644 index 00000000..faa8ad55 --- /dev/null +++ b/springnext-profile.gradle @@ -0,0 +1,10 @@ +/** + * Enable with "-Pprofile=spring5" + */ + +ext.springVersion = "5.0.1.BUILD-SNAPSHOT" +ext.springSecurityVersion = "5.0.0.BUILD-SNAPSHOT" + +repositories { + maven { url 'https://repo.spring.io/libs-snapshot' } +}