简体   繁体   中英

WSSecurityException - An error was discovered processing the <wsse:Security> header

I built a CXF based soap web service and i was trying to add some security aspects using the WS-Security by following the steps of this tutorial.

I got the An error was discovered processing the header

Here are the important classes that add the security aspects to the soap ws

ServerPasswordCallback.java

    import java.io.IOException;
    import java.util.ResourceBundle;
    import javax.security.auth.callback.Callback;
    import javax.security.auth.callback.CallbackHandler;
    import javax.security.auth.callback.UnsupportedCallbackException;
    import org.apache.wss4j.common.ext.WSPasswordCallback;

    public class ServerPasswordCallback implements CallbackHandler {
        private static final String BUNDLE_LOCATION = "auth";
        private static final String PASSWORD_PROPERTY_NAME = "auth.manager.password";

        private static String password;

        static {
            final ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_LOCATION);
            password = bundle.getString(PASSWORD_PROPERTY_NAME);
        }

        @Override
        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
            WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
            pc.setPassword(password);
        }
    }

ClientPasswordCallback.java

    import java.io.IOException;
    import java.util.ResourceBundle;
    import javax.security.auth.callback.Callback;
    import javax.security.auth.callback.CallbackHandler;
    import javax.security.auth.callback.UnsupportedCallbackException;
    import org.apache.wss4j.common.ext.WSPasswordCallback;


    public class ClientPasswordCallback implements CallbackHandler {

        private static final String BUNDLE_LOCATION = "auth";
        private static final String PASSWORD_PROPERTY_NAME = "auth.manager.password";
        private static String password;

        static {
            final ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_LOCATION);
            password = bundle.getString(PASSWORD_PROPERTY_NAME);
        }

        @Override
        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
            WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
            pc.setPassword(password);
        }
    }

AuthServiceFactory.java

    public final class AuthServiceFactory {

        private static final ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {
                    "com/company/auth/service/cxfClient.xml"
                });

        public AuthServiceFactory() {
        }

        public AuthService getService() {
            return (AuthService) context.getBean("client");
        }
    }

auth_fr_FR

auth.manager.password=*****

cxfClient.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <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:jaxrs="http://cxf.apache.org/jaxrs"
        xsi:schemaLocation="http://cxf.apache.org/jaxws 
                            http://cxf.apache.org/schemas/jaxws.xsd
                            http://www.springframework.org/schema/beans 
                            http://www.springframework.org/schema/beans/spring-beans.xsd
                            http://cxf.apache.org/jaxrs 
                            http://cxf.apache.org/schemas/jaxrs.xsd">

        <bean id="proxyFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
            <property name="serviceClass" value="com.company.auth.service.AuthService" />
            <property name="address"
                value="http://localhost:8080/CXFSOAP-WebService/corporateAuth" />
            <property name="inInterceptors">
                <list>
                    <ref bean="logIn" />
                </list>
            </property>
            <property name="outInterceptors">
                <list>
                    <ref bean="logOut" />
                    <ref bean="saajOut" />
                    <ref bean="wss4jOut" />
                </list>
            </property>
        </bean>

        <bean id="client" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean"
            factory-bean="proxyFactory" factory-method="create" />

        <bean id="logIn" class="org.apache.cxf.interceptor.LoggingInInterceptor" />
        <bean id="logOut" class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
        <bean id="saajOut" class="org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor" />
        <bean id="wss4jOut" class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">
            <constructor-arg>
                <map>
                    <entry key="action" value="UsernameToken" />
                    <entry key="user" value="ws-client" />
                    <entry key="passwordType" value="PasswordText" />
                    <entry key="passwordCallbackClass" value="com.company.auth.service.ClientPasswordCallback" />
                </map>
            </constructor-arg>
        </bean>
    </beans>

This file is for the client configuration

beans.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <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:jaxrs="http://cxf.apache.org/jaxrs"
        xsi:schemaLocation="http://cxf.apache.org/jaxws 
                            http://cxf.apache.org/schemas/jaxws.xsd
                            http://www.springframework.org/schema/beans 
                            http://www.springframework.org/schema/beans/spring-beans.xsd
                            http://cxf.apache.org/jaxrs 
                            http://cxf.apache.org/schemas/jaxrs.xsd">

        <jaxws:endpoint id="bookShelfService"
            implementor="com.company.auth.service.AuthServiceImpl" address="/corporateAuth">
            <jaxws:inInterceptors>
                <bean class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor"></bean>
                <bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
                    <constructor-arg>
                        <map>
                            <entry key="action" value="UsernameToken" />
                            <entry key="passwordType" value="PasswordText" />
                            <entry key="passwordCallbackClass" value="com.company.auth.service.ServerPasswordCallback"></entry>
                        </map>
                    </constructor-arg>
                </bean>
            </jaxws:inInterceptors>
        </jaxws:endpoint>

    </beans>

This file is for the server configuration

Client.java

    import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
    import com.company.auth.bean.Employee;
    import com.company.auth.service.AuthService;

    public class Client {

        public Client() {
            super();
        }

        public static void main(String[] args) {
            JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
            factory.setServiceClass(AuthService.class);
            factory.setAddress("http://localhost:8080/CXFSOAP-WebService/corporateAuth");
            AuthService client = (AuthService) factory.create();
            Employee employee = client.getEmployee("22222");
            System.out.println("Server said: "+employee.getLastName()+" "+employee.getFirstName());
            System.exit(0);
        }
    }

This is the client code that consumes the soap web service.

before adding the security configuration, the server was up and running and the client consumed the function of the soap api successfully but after the security modification, when the client attempts to use the web service function i get this error

    org.apache.cxf.binding.soap.SoapFault: A security error was encountered when verifying the message
    at org.apache.cxf.ws.security.wss4j.WSS4JUtils.createSoapFault(WSS4JUtils.java:216)
    at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessageInternal(WSS4JInInterceptor.java:329)
    at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessage(WSS4JInInterceptor.java:184)
    at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessage(WSS4JInInterceptor.java:93)
    at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
    at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)

Caused by: org.apache.wss4j.common.ext.WSSecurityException: An error was discovered processing the header

    at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.checkActions(WSS4JInInterceptor.java:370)
    at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessageInternal(WSS4JInInterceptor.java:313)
    ... 34 more

I tried to manually add some wsse headers in the soap envelope but it didn't work.

I solved my problem by modifying the AuthServiceFactory.java class and the ClientPasswordCallback.java and the descriptor deployment file and i added a auth2_Fr_fr.properties file.

AuthServiceFactory.java

    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import com.company.auth.bean.Employee;

    public final class AuthServiceFactory {

        private static final ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
                new String[] { "com/company/auth/service/cxfClient.xml" });

        public AuthServiceFactory() {
        }

        public AuthService getService() {
            return (AuthService) context.getBean("client");
        }

        public static void main(String[] args) {
            AuthServiceFactory authSer = new AuthServiceFactory();
            AuthService client = authSer.getService();
            Employee employee = client.getEmployee("22222");
            System.out.println("Server said: " + employee.getLastName() + " " + employee.getFirstName());
            System.exit(0);
        }
}

ClientPasswordCallback.java

    import java.io.IOException;
    import java.util.ResourceBundle;
    import javax.security.auth.callback.Callback;
    import javax.security.auth.callback.CallbackHandler;
    import javax.security.auth.callback.UnsupportedCallbackException;
    import org.apache.wss4j.common.ext.WSPasswordCallback;

    public class ClientPasswordCallback implements CallbackHandler {

        private static final String BUNDLE_LOCATION = "auth2";
        private static final String PASSWORD_PROPERTY_NAME = "auth.manager.password";
        private static String password;

        static {
            final ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_LOCATION);
            password = bundle.getString(PASSWORD_PROPERTY_NAME);
        }

        @Override
        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
            WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
            pc.setPassword(password);
        }
    }

auth2_fr_Fr.properties

    auth.manager.password=123456

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM