You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by ff...@apache.org on 2018/06/12 06:27:54 UTC

[cxf] branch master updated: [CXF-7756]JAASLoginInterceptor with server continuation enabled will cause the interceptor before ServiceInvokerInterceptor get invoked twice

This is an automated email from the ASF dual-hosted git repository.

ffang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cxf.git


The following commit(s) were added to refs/heads/master by this push:
     new 812bdd0  [CXF-7756]JAASLoginInterceptor with server continuation enabled will cause the interceptor before ServiceInvokerInterceptor get invoked twice
812bdd0 is described below

commit 812bdd08e1374766edca1a3eda834a6d1c406723
Author: Freeman Fang <fr...@gmail.com>
AuthorDate: Tue Jun 12 14:27:13 2018 +0800

    [CXF-7756]JAASLoginInterceptor with server continuation enabled will cause the interceptor before ServiceInvokerInterceptor get invoked twice
---
 .../interceptor/security/JAASLoginInterceptor.java |  1 +
 .../systest/ws/basicauth/BasicAuthJAASTest.java    | 87 +++++++++++++++++++++
 .../basicauth/BeforeServiceInvokerInterceptor.java | 39 ++++++++++
 .../cxf/systest/ws/basicauth/JAASServer.java       | 77 ++++++++++++++++++
 .../ws/basicauth/TestUserPasswordLoginModule.java  | 91 ++++++++++++++++++++++
 .../ws/common/DoubleItImplContinuation.java        | 72 +++++++++++++++++
 .../systest/ws/basicauth/server-continuation.xml   | 52 +++++++++++++
 7 files changed, 419 insertions(+)

diff --git a/core/src/main/java/org/apache/cxf/interceptor/security/JAASLoginInterceptor.java b/core/src/main/java/org/apache/cxf/interceptor/security/JAASLoginInterceptor.java
index 1aa4225..06801ff 100644
--- a/core/src/main/java/org/apache/cxf/interceptor/security/JAASLoginInterceptor.java
+++ b/core/src/main/java/org/apache/cxf/interceptor/security/JAASLoginInterceptor.java
@@ -152,6 +152,7 @@ public class JAASLoginInterceptor extends AbstractPhaseInterceptor<Message> {
                     public Void run() {
                         InterceptorChain chain = message.getInterceptorChain();
                         if (chain != null) {
+                            message.put("suspend.chain.on.current.interceptor", Boolean.TRUE);
                             chain.doIntercept(message);
                         }
                         return null;
diff --git a/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/basicauth/BasicAuthJAASTest.java b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/basicauth/BasicAuthJAASTest.java
new file mode 100644
index 0000000..e32413f
--- /dev/null
+++ b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/basicauth/BasicAuthJAASTest.java
@@ -0,0 +1,87 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.cxf.systest.ws.basicauth;
+
+import java.net.URL;
+
+import javax.xml.namespace.QName;
+import javax.xml.ws.Service;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.bus.spring.SpringBusFactory;
+import org.apache.cxf.systest.ws.common.SecurityTestUtil;
+import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
+import org.example.contract.doubleit.DoubleItPortType;
+
+import org.junit.BeforeClass;
+
+/**
+ * A test for Basic Auth using JAASLoginInterceptor.
+ * To ensure the Interceptor Chain resume to use the 
+ * expected next interceptor
+ */
+public class BasicAuthJAASTest extends AbstractBusClientServerTestBase {
+    static final String PORT = allocatePort(Server.class);
+
+    private static final String NAMESPACE = "http://www.example.org/contract/DoubleIt";
+    private static final QName SERVICE_QNAME = new QName(NAMESPACE, "DoubleItService");
+
+    @BeforeClass
+    public static void startServers() throws Exception {
+        assertTrue(
+            "Server failed to launch",
+            // run the server in the same process
+            // set this to false to fork
+            launchServer(JAASServer.class, true)
+        );
+    }
+
+    @org.junit.AfterClass
+    public static void cleanup() throws Exception {
+        SecurityTestUtil.cleanup();
+        stopAllServers();
+    }
+
+    @org.junit.Test
+    public void testBasicAuth() throws Exception {
+
+        SpringBusFactory bf = new SpringBusFactory();
+        URL busFile = BasicAuthJAASTest.class.getResource("client.xml");
+
+        Bus bus = bf.createBus(busFile.toString());
+        BusFactory.setDefaultBus(bus);
+        BusFactory.setThreadDefaultBus(bus);
+
+        URL wsdl = BasicAuthJAASTest.class.getResource("DoubleItBasicAuth.wsdl");
+        Service service = Service.create(wsdl, SERVICE_QNAME);
+        QName portQName = new QName(NAMESPACE, "DoubleItBasicAuthPort");
+        DoubleItPortType utPort =
+                service.getPort(portQName, DoubleItPortType.class);
+        updateAddressPort(utPort, PORT);
+
+        assertEquals(50, utPort.doubleIt(25));
+        //BeforeServiceInvokerInterceptor should be invoked only once 
+        assertEquals(1, BeforeServiceInvokerInterceptor.counter);
+
+        ((java.io.Closeable)utPort).close();
+        bus.shutdown(true);
+    }
+}
\ No newline at end of file
diff --git a/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/basicauth/BeforeServiceInvokerInterceptor.java b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/basicauth/BeforeServiceInvokerInterceptor.java
new file mode 100644
index 0000000..861c6ee
--- /dev/null
+++ b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/basicauth/BeforeServiceInvokerInterceptor.java
@@ -0,0 +1,39 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.cxf.systest.ws.basicauth;
+
+import org.apache.cxf.interceptor.Fault;
+import org.apache.cxf.interceptor.ServiceInvokerInterceptor;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.AbstractPhaseInterceptor;
+import org.apache.cxf.phase.Phase;
+
+public class BeforeServiceInvokerInterceptor extends AbstractPhaseInterceptor<Message> {
+    static int counter;
+    public BeforeServiceInvokerInterceptor() {
+        super(Phase.INVOKE);
+        addBefore(ServiceInvokerInterceptor.class.getName());
+    }
+
+    @Override
+    public void handleMessage(Message message) throws Fault {
+        counter = counter + 1;
+    }
+}
diff --git a/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/basicauth/JAASServer.java b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/basicauth/JAASServer.java
new file mode 100644
index 0000000..3a3d6ca
--- /dev/null
+++ b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/basicauth/JAASServer.java
@@ -0,0 +1,77 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.cxf.systest.ws.basicauth;
+
+import java.net.URL;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.security.auth.login.AppConfigurationEntry;
+import javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag;
+import javax.security.auth.login.Configuration;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.bus.spring.SpringBusFactory;
+import org.apache.cxf.interceptor.security.JAASLoginInterceptor;
+import org.apache.cxf.testutil.common.AbstractBusTestServerBase;
+
+public class JAASServer extends AbstractBusTestServerBase {
+
+    public JAASServer() {
+
+    }
+
+    protected void run()  {
+        URL busFile = JAASServer.class.getResource("server-continuation.xml");
+        Bus busLocal = new SpringBusFactory().createBus(busFile);
+        BusFactory.setDefaultBus(busLocal);
+        busLocal.getInInterceptors().add(this.createTestJaasLoginInterceptor());
+        busLocal.getInInterceptors().add(new BeforeServiceInvokerInterceptor());
+        setBus(busLocal);
+
+        try {
+            new JAASServer();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+    
+    private JAASLoginInterceptor createTestJaasLoginInterceptor() {
+        JAASLoginInterceptor jaasInt = new JAASLoginInterceptor();
+        jaasInt.setReportFault(true);
+        Configuration config = new Configuration() {
+
+            @Override
+            public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
+                Map<String, String> options = new HashMap<>();
+                AppConfigurationEntry configEntry = new AppConfigurationEntry(
+                                                                              TestUserPasswordLoginModule.class
+                                                                                  .getName(),
+                                                                              LoginModuleControlFlag.REQUIRED,
+                                                                              options);
+                return Collections.singleton(configEntry).toArray(new AppConfigurationEntry[] {});
+            }
+        };
+        jaasInt.setLoginConfig(config);
+        return jaasInt;
+    }
+}
diff --git a/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/basicauth/TestUserPasswordLoginModule.java b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/basicauth/TestUserPasswordLoginModule.java
new file mode 100644
index 0000000..28d91ef
--- /dev/null
+++ b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/basicauth/TestUserPasswordLoginModule.java
@@ -0,0 +1,91 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.cxf.systest.ws.basicauth;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.spi.LoginModule;
+
+import org.apache.cxf.common.security.SimpleGroup;
+import org.apache.cxf.common.security.SimplePrincipal;
+
+public class TestUserPasswordLoginModule implements LoginModule {
+
+    public static final String TESTGROUP = "testgroup";
+    public static final String TESTPASS = "ecilA";
+    public static final String TESTUSER = "Alice";
+    private Subject subject;
+    private CallbackHandler callbackHandler;
+
+    @Override
+    public void initialize(Subject subject2, CallbackHandler callbackHandler2, Map<String, ?> sharedState,
+                           Map<String, ?> options) {
+        this.subject = subject2;
+        this.callbackHandler = callbackHandler2;
+    }
+
+    @Override
+    public boolean login() throws LoginException {
+        NameCallback nameCallback = new NameCallback("User");
+        PasswordCallback passwordCallback = new PasswordCallback("Password", false);
+        Callback[] callbacks = new Callback[] {nameCallback, passwordCallback};
+        try {
+            this.callbackHandler.handle(callbacks);
+        } catch (IOException e) {
+            throw new LoginException(e.getMessage());
+        } catch (UnsupportedCallbackException e) {
+            throw new LoginException(e.getMessage());
+        }
+        String userName = nameCallback.getName();
+        String password = new String(passwordCallback.getPassword());
+        if (!TESTUSER.equals(userName)) {
+            throw new LoginException("wrong username");
+        }
+        if (!TESTPASS.equals(password)) {
+            throw new LoginException("wrong password");
+        }
+        subject.getPrincipals().add(new SimplePrincipal(userName));
+        subject.getPrincipals().add(new SimpleGroup(TESTGROUP));
+        return true;
+    }
+
+    @Override
+    public boolean commit() throws LoginException {
+        return true;
+    }
+
+    @Override
+    public boolean abort() throws LoginException {
+        return false;
+    }
+
+    @Override
+    public boolean logout() throws LoginException {
+        return false;
+    }
+
+}
diff --git a/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/common/DoubleItImplContinuation.java b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/common/DoubleItImplContinuation.java
new file mode 100644
index 0000000..aa6dbce
--- /dev/null
+++ b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/common/DoubleItImplContinuation.java
@@ -0,0 +1,72 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.cxf.systest.ws.common;
+
+
+
+import javax.annotation.Resource;
+import javax.jws.WebService;
+import javax.xml.ws.WebServiceContext;
+
+import org.apache.cxf.continuations.Continuation;
+import org.apache.cxf.continuations.ContinuationProvider;
+import org.apache.cxf.feature.Features;
+import org.example.contract.doubleit.DoubleItFault;
+import org.example.contract.doubleit.DoubleItPortType;
+
+@WebService(targetNamespace = "http://www.example.org/contract/DoubleIt",
+            serviceName = "DoubleItService",
+            endpointInterface = "org.example.contract.doubleit.DoubleItPortType")
+@Features(features = "org.apache.cxf.feature.LoggingFeature")
+public class DoubleItImplContinuation implements DoubleItPortType {
+    
+
+    @Resource
+    private WebServiceContext context;
+
+    public int doubleIt(int numberToDouble) throws DoubleItFault {
+        Continuation continuation = getContinuation(numberToDouble);
+        if (continuation == null) {
+            throw new RuntimeException("Failed to get continuation");
+        }
+        synchronized (continuation) {
+            if (continuation.isNew()) {
+                continuation.suspend(5000);
+            } else {
+                
+                if (numberToDouble == 0) {
+                    throw new DoubleItFault("0 can't be doubled!");
+                }
+                return numberToDouble * 2;
+            }
+        }
+        // unreachable
+        return 0;
+        
+    }
+    
+    
+
+    private Continuation getContinuation(Integer name) {
+        ContinuationProvider provider =
+            (ContinuationProvider)context.getMessageContext().get(ContinuationProvider.class.getName());
+        return provider.getContinuation();
+    }
+
+}
diff --git a/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/basicauth/server-continuation.xml b/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/basicauth/server-continuation.xml
new file mode 100644
index 0000000..a3d35ec
--- /dev/null
+++ b/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/basicauth/server-continuation.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:http="http://cxf.apache.org/transports/http/configuration" xmlns:httpj="http://cxf.apache.org/transports/http-jetty/configuration" xmlns:sec="http://cxf.apache.org/configuration/security" xmlns:cxf="http://cxf.apache.org/core" xmlns:p="http://cxf.apache.org/policy" xsi:schemaLocation="         http://www.springframework.org/schem [...]
+    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
+    <cxf:bus>
+        <cxf:features>
+            <p:policies/>
+            <cxf:logging/>
+        </cxf:features>
+    </cxf:bus>
+    <!-- -->
+    <!-- Any services listening on port 9009 must use the following -->
+    <!-- Transport Layer Security (TLS) settings -->
+    <!-- -->
+    <httpj:engine-factory id="tls-settings">
+        <httpj:engine port="${testutil.ports.basicauth.Server}">
+            <httpj:tlsServerParameters>
+                <sec:keyManagers keyPassword="password">
+                    <sec:keyStore type="jks" password="password" resource="keys/Bethal.jks"/>
+                </sec:keyManagers>
+                <sec:trustManagers>
+                    <sec:keyStore type="jks" password="password" resource="keys/Truststore.jks"/>
+                </sec:trustManagers>
+                <sec:clientAuthentication want="true" required="false"/>
+            </httpj:tlsServerParameters>
+        </httpj:engine>
+    </httpj:engine-factory>
+    <jaxws:endpoint xmlns:s="http://www.example.org/contract/DoubleIt" id="BasicAuth" address="https://localhost:${testutil.ports.basicauth.Server}/DoubleItBasicAuth" serviceName="s:DoubleItService" endpointName="s:DoubleItBasicAuthPort" implementor="org.apache.cxf.systest.ws.common.DoubleItImplContinuation" wsdlLocation="org/apache/cxf/systest/ws/basicauth/DoubleItBasicAuth.wsdl" depends-on="tls-settings">
+        <jaxws:properties />
+    </jaxws:endpoint>
+    <jaxws:endpoint xmlns:s="http://www.example.org/contract/DoubleIt" id="BasicAuth2" address="https://localhost:${testutil.ports.basicauth.Server}/DoubleItBasicAuth2" serviceName="s:DoubleItService" endpointName="s:DoubleItBasicAuthPort2" implementor="org.apache.cxf.systest.ws.common.DoubleItImplContinuation" wsdlLocation="org/apache/cxf/systest/ws/basicauth/DoubleItBasicAuth.wsdl" depends-on="tls-settings">
+        <jaxws:properties />
+    </jaxws:endpoint>
+    
+</beans>

-- 
To stop receiving notification emails like this one, please contact
ffang@apache.org.