2

我已经尝试用谷歌搜索这个问题了几天,但我仍然卡住了,所以我会尝试在这里寻求一些帮助。

这是情况。我正在开发的 EJB 必须连接到安全的 Web 服务。连接需要相互认证,所以我有一个公共ID链和一个个人证书。我从文件中加载这些信息,并构建我自己的 SSLSocketFactory(Apache HttpClient 之一)

    // Queste proprietà servono perché senza di loro WebSphere 6.1 non
    // capisce un cazzo
    Security.setProperty("security.provider.1", "com.ibm.jsse2.IBMJSSEProvider2");
    Security.setProperty("security.provider.2", "com.ibm.crypto.fips.provider.IBMJCEFIPS");
    Security.setProperty("security.provider.3", "com.ibm.crypto.provider.IBMJCE");
    Security.setProperty("security.provider.4", "com.ibm.security.jgss.IBMJGSSProvider");
    Security.setProperty("security.provider.5", "com.ibm.security.cert.IBMCertPath");
    Security.setProperty("security.provider.6", "com.ibm.security.sasl.IBMSASL");
    Security.setProperty("ssl.SocketFactory.provider", "com.ibm.jsse2.SSLSocketFactoryImpl");
    Security.setProperty("ssl.ServerSocketFactory.provider", "com.ibm.jsse2.SSLServerSocketFactoryImpl");

    // d) SETUP KS, TS e SSL
    InitialContext ctx = new InitialContext();

    // keystore
    KeyManager[] keyManagers;
    TrustManager[] trustManagers;
    try {
        URI keyStoreUri = ((URL) ctx.lookup(JNDI_INPS_KEY_STORE_PATH))
                .toURI();
        String keyStorePassword = "test2012";

        KeyStore keyStore = loadKeyStoreFromFile(keyStoreUri,
                keyStorePassword);

        KeyManagerFactory keyManagerFactory = KeyManagerFactory
                .getInstance("IBMX509");
        keyManagerFactory.init(keyStore, keyStorePassword.toCharArray());

        keyManagers = keyManagerFactory.getKeyManagers();

        URI trustStoreUri = ((URL) ctx.lookup(JNDI_INPS_TRUST_STORE_PATH))
                .toURI();
        String trustStorePassword = "inpsChain";

        KeyStore trustStore = loadKeyStoreFromFile(trustStoreUri,
                trustStorePassword);

        TrustManagerFactory trustManagerFactory = TrustManagerFactory
                .getInstance("IBMX509");
        trustManagerFactory.init(trustStore);

        trustManagers = trustManagerFactory.getTrustManagers();
    } catch (NameNotFoundException ex) {
        throw new ErroreApplicativo("USINPS001", ErroreApplicativo.ERRORE,
                "", null);
    }

    SSLContext sslCtx = SSLContext.getInstance("TLS");
    sslCtx.init(keyManagers,
            new TrustManager[] { new TrustfulTrustManager() }, null);

    SSLSocketFactory sslSocketFactory = new SSLSocketFactory(sslCtx);
    Scheme httpsScheme = new Scheme("https", HTTPS_PORT, sslSocketFactory);
    Scheme httpScheme = new Scheme("http", HTTP_PORT, sslSocketFactory); // Which socket factory should I use?

    final SchemeRegistry schemeRegistry = new SchemeRegistry();
    schemeRegistry.register(httpScheme);
    schemeRegistry.register(httpsScheme);

    PoolingClientConnectionManager connManager = new PoolingClientConnectionManager(
            schemeRegistry);

密码是临时写在代码中的,但是一旦解决方案起作用,它们就会被参数化。

我必须使用代理来拨打电话。我从来没有做过这种事情,但我想我必须使用 http 隧道,因为证书在我的服务器中,而不是在代理中。所以我设置了一个 HttpRoute (仍然是一个 HttpClient 类)......

    System.setProperty("java.net.useSystemProxies", "false");

    Resources res = new Resources();
    String proxyHost = res.get(PROXY_HOST);
    int proxyPort = Integer.parseInt(res.get(PROXY_PORT));

    final HttpHost proxy = new HttpHost(proxyHost, proxyPort, "http");


    String inpsProtocol = inpsHostURI.getScheme();
    String inpsHostName = inpsHostURI.getHost();

    final HttpHost inpsHost = new HttpHost(inpsHostName, HTTPS_PORT,
            inpsProtocol);


    HttpRoutePlanner planner = new HttpRoutePlanner() {
        public HttpRoute determineRoute(HttpHost arg0, HttpRequest arg1,
                HttpContext arg2) throws HttpException {
            // TODO Stub di metodo generato automaticamente
            try {
                return new HttpRoute(inpsHost, Inet4Address.getLocalHost(),
                        proxy, true, TunnelType.TUNNELLED,
                        LayerType.LAYERED);
            } catch (UnknownHostException e) {
                return null;
            }
        }
    };

...并发送消息...

    DefaultHttpClient httpClient = new DefaultHttpClient(connManager);
    httpClient.setRoutePlanner(planner);

    HttpResponse resp = httpClient.execute(httpPost);

答案总是一样的:HTTP500,我不确定是来自代理还是我正在调用的 SSL 服务器。

一些问题:

  1. 我应该为 HTTP 方案使用哪个套接字工厂?我应该使用与其他套接字相同的 SSL 工厂还是 HTTPClient 附带的普通套接字工厂?

  2. 什么是 LayerType.LAYERED 参数,它是什么意思?

4

0 回答 0