【问题标题】:Error with soap requests on tomcatTomcat上的soap请求错误
【发布时间】:2018-03-31 02:53:24
【问题描述】:

我有一个运行良好的简单 SOAP 客户端应用程序。 但是当我将它的一段代码放入其他 web 项目(tomcat 8.5)时,它就不起作用了。 它抛出异常:

2017 年 10 月 19 日 11:10:48.019 严重 [http-nio-8080-exec-10] com.sun.xml.messaging.saaj.client.p2p.HttpSOAPConnection.post SAAJ0008:不良反应;禁止的 Ошибка при отправке сообщения SOAP-серверу: com.sun.xml.messaging.saaj.SOAPExceptionImpl: com.sun.xml.messaging.saaj.SOAPExceptionImpl:错误响应: (403禁止在 com.sun.xml.messaging.saaj.client.p2p.HttpSOAPConnection.call(HttpSOAPConnection.java:164) 在 ls.common.objects.SOAPMessageSender.callSoapWebService(SOAPMessageSender.java:72) 在 ls.webSite.common.servlets.cli_GetMKBClientByIIN.processRequests(cli_GetMKBClientByIIN.java:49) 在 common.servlets.prototypes.AbstractServlet.processRequest(AbstractServlet.java:369) 在 common.servlets.prototypes.AbstractServlet.doPost(AbstractServlet.java:503) 在 javax.servlet.http.HttpServlet.service(HttpServlet.java:661) 在 javax.servlet.http.HttpServlet.service(HttpServlet.java:742) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 在 org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 在 org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) 在 org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) 在 org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) 在 org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) 在 org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80) 在 org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:650) 在 org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) 在 org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) 在 org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799) 在 org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) 在 org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) 在 org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1457) 在 org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) 在 org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) 在 java.lang.Thread.run(Thread.java:748) 引起: com.sun.xml.messaging.saaj.SOAPExceptionImpl:错误响应: (403禁止在 com.sun.xml.messaging.saaj.client.p2p.HttpSOAPConnection.post(HttpSOAPConnection.java:276) 在 com.sun.xml.messaging.saaj.client.p2p.HttpSOAPConnection.call(HttpSOAPConnection.java:160) ... 28 更多

为什么它不适用于 Web 项目?是密钥库的问题吗? 这是我的代码示例:

public class InsuranceSOAPMessageCreator {

    public static SOAPMessage createSOAPMessageFromXML(String soapActionFull, String sourceXmlFile, Map<String, String> params)
            throws IOException, SOAPException {

        Path path  = Paths.get(sourceXmlFile);
        String xml = new String(Files.readAllBytes(path));

        MessageFactory mf = MessageFactory.newInstance();

        if(params != null){
            for(Map.Entry entry : params.entrySet()){
                xml = xml.replace("##$[" + entry.getKey().toString() + "]$##", entry.getValue().toString());
            }
        }

        SOAPMessage msg = mf.createMessage(new MimeHeaders(),
                new ByteArrayInputStream(xml.getBytes(Charset.forName("UTF-8"))));

        msg.getMimeHeaders().addHeader("SOAPAction", soapActionFull);

        return msg;
    }


}

public class SOAPMessageSender {

        private String nameSpaceURI;
        private String endpointUrl;
        private String trustStore;
        private String trustStorePassword;
        private String keyStore;
        private String keyStorePassword;
        private SOAPMessage soapResponse;

        public SOAPMessageSender(){
        }

        public SOAPMessageSender(String endpointUrl, String nameSpaceURI, String trustStore, String trustStorePassword,
                                 String keyStore, String keyStorePassword){

            this.nameSpaceURI = nameSpaceURI;
            this.keyStorePassword = keyStorePassword;
            this.keyStore = keyStore;
            this.trustStorePassword = trustStorePassword;
            this.trustStore = trustStore;
            this.endpointUrl = endpointUrl;
            setSystemProperties();
        }

        public void setSystemProperties(){
            System.setProperty("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol");
            System.setProperty("com.ibm.ssl.performURLHostNameVerification", "true");

            System.setProperty("javax.net.ssl.trustStore", trustStore);
            System.setProperty("javax.net.ssl.trustStorePassword", trustStorePassword);

            System.setProperty("javax.net.ssl.keyStore", keyStore);
            System.setProperty("javax.net.ssl.keyStorePassword",keyStorePassword);
            System.setProperty("javax.net.ssl.keyStoreType", "jks");
        }

        public String callSoapWebService(String soapAction, String sourceXml, Map<String, String> params)  {

            try {

                SOAPConnectionFactory scf = SOAPConnectionFactory.newInstance();
                SOAPConnection sc = scf.createConnection();
                /*SOAPMessage requestMsg = createSOAPMessageFromXML(nameSpaceURI + "/" + soapAction,
                        sourceXml, params);*/
                //doTrustToCertificates();
                soapResponse = sc.call(InsuranceSOAPMessageCreator.createSOAPMessageFromXML(soapAction,
                        sourceXml, params), endpointUrl);

                ByteArrayOutputStream out = new ByteArrayOutputStream();
                soapResponse.writeTo(out);

                sc.close();

                return out.toString();

            } catch (Exception e) {
                System.err.println("Ошибка при отправке сообщения SOAP-серверу:" + endpointUrl);
                e.printStackTrace();
            }

            return null;
        }

        ... 

        public static void main(String[] args){
            //works fine here (on local run main method)
            Map <String, String> authenticationData = new HashMap<>();
            authenticationData.put("login", "user");
            authenticationData.put("password", "pass");

            SOAPMessageSender me = new SOAPMessageSender("https://somehost/someservice.asmx",
                    "https://someuri",
                    "/usr/lib/jvm/java-8-oracle/jre/lib/security/cacerts",
                    "password",
                    "/path/to/mykey.jks",
                    "password");
            String resultXml = me.callSoapWebService("someaction",
                    "/path/to/AuthenticateUser.xml", authenticationData);
            System.out.println(resultXml);
        }
    }

【问题讨论】:

    标签: java tomcat ssl soap-client


    【解决方案1】:

    问题已解决。 Tomcat 只是无法获取 System.setProperty() 中指定的 jks 文件,我通过使用 java.security.KeyStore 对象解决了它。这是我添加的方法:

    public void loadKeyStoreAndDoTrustToCertificates(String ksFile, String ksPass, String tsAlgo) throws Exception {
            FileInputStream ksCert = new FileInputStream(ksFile);
    
            KeyStore ks = KeyStore.getInstance(keyStoreType);
            ks.load(ksCert, ksPass.toCharArray());
            KeyManagerFactory kmf = KeyManagerFactory.getInstance(tsAlgo);
            kmf.init(ks, ksPass.toCharArray());
    
            TrustManagerFactory tmf = TrustManagerFactory.getInstance(tsAlgo);
            tmf.init(ks);
    
            Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
    
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(kmf.getKeyManagers(), null, new SecureRandom());
    
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
            HostnameVerifier hv = new HostnameVerifier() {
                public boolean verify(String urlHostName, SSLSession session) {
                    if (!urlHostName.equalsIgnoreCase(session.getPeerHost())) {
                        System.out.println("Ошибка: URL хост '" + urlHostName + "' отличается SSL хоста'" + session.getPeerHost() + "'.");
                    }
                    return true;
                }
            };
            HttpsURLConnection.setDefaultHostnameVerifier(hv);
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多