2017-10-19 129 views
0

我有一个简单的SOAP客户端应用程序,它的工作非常完美。 但是,当我把它的代码片段放到其他web项目(tomcat 8.5)中时,它不起作用。 它抛出异常:tomcat上的soap请求出错

19-OCT-2017 11:10:48.019严重[HTTP-NIO-8080-EXEC-10] com.sun.xml.messaging.saaj.client.p2p.HttpSOAPConnection。后 SAAJ0008:错误的响应;故宫 ОшибкаприотправкесообщенияSOAP-серверу: com.sun.xml.messaging.saaj.SOAPExceptionImpl: com.sun.xml.messaging.saaj.SOAPExceptionImpl:不良反应: (403Forbidden在 了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) at common.servlets.prototypes.AbstractServlet.processRequest(AbstractServlet.java:369) at comm javax.servlet.http.HttpServlet.service(HttpServlet.java:661) javax.servlet.http.HttpServlet.service(HttpServlet.java:http://www.ibm.com/developerworks/cn/education/webservices/default.mspx)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(ApplicationFi lterChain.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.a pache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) 在 org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) 在 org.apache.coyote.http11.Http11Processor。服务(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) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor。java:624) at org.apache.tomcat.util.threads.TaskThread $ WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:748)引起的: com .sun.xml.messaging.saaj.SOAPExceptionImpl:坏响应: (403Forbidden在 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项目的工作?是不是与密钥存储问题? 这里一世的我的码S例如:

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); 
     } 
    } 

回答

0

问题得到解决。 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); 
    }