zoukankan      html  css  js  c++  java
  • WebSphere应用服务器中https 请求协议的相关注意事项(服务器使用代理上Internet)

    最近遇到个需求需要web服务器应用通过https方式请求外部Internet服务器的接口,一开始本地测试时使用以下代码:

    String businessCode = "SH30580";
    GenerateXml xml = new GenerateXml();
    String xmlContent = xml.writeXmlString(businessCode);
    // 创建SSLContext对象,并使用我们指定的信任管理器初始化
    SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
    sslContext.init(null, new TrustManager[] {new X509TrustForMSL()},new java.security.SecureRandom());
    // 从上述SSLContext对象中得到SSLSocketFactory对象
    SSLSocketFactory ssf = sslContext.getSocketFactory();

    // 创建URL对象
    URL myURL = new URL("https://211.144.221.138/mslws/Services/rsa/RsaWebService.svc/security/validateagencyqualification");


    System.setProperty("java.protocol.handler.pkgs", "javax.net.ssl");
    HostnameVerifier hv = new HostnameVerifier() {
    public boolean verify(String urlHostName, SSLSession session) {
    return true;
    }
    };
    HttpsURLConnection.setDefaultHostnameVerifier(hv);

    // 创建HttpsURLConnection对象,并设置其SSLSocketFactory对象
    Proxy proxy = new Proxy(Proxy.Type.HTTP,new InetSocketAddress("10.38.194.30", 8080));//因为服务器使用代理上Internet,设置代理的ip和端口号
    HttpsURLConnection httpsConn = (HttpsURLConnection) myURL.openConnection();
    httpsConn.setRequestProperty( "Proxy-Authorization", "Basic " + new sun.misc.BASE64Encoder().encode("用户名:密码".getBytes()) );//设置用户名和密码
    httpsConn.setSSLSocketFactory(ssf);
    // 以POST方式提交
    httpsConn.setRequestMethod("POST");
    // 设置连接输出
    httpsConn.setDoInput(true);
    httpsConn.setDoOutput(true);
    // Post 请求不能使用缓存
    httpsConn.setUseCaches(false);
    httpsConn.setRequestProperty("Content-Type","application/xml");
    // httpsConn.connect();

    //获取输出流
    OutputStream os = httpsConn.getOutputStream();
    // // 设置输出流字符集
    os.write(xmlContent.getBytes("UTF-8"));
    os.flush();
    os.close();

    // 取得该连接的输入流,以读取响应内容
    InputStreamReader insr = new InputStreamReader(httpsConn.getInputStream());
    // 读取服务器的响应内容并显示
    int respInt = insr.read();
    while (respInt != -1) {
    System.out.print((char) respInt);
    respInt = insr.read();
    }

    import java.io.FileInputStream;
    import java.security.KeyStore;
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;

    import javax.net.ssl.TrustManager;
    import javax.net.ssl.TrustManagerFactory;
    import javax.net.ssl.X509TrustManager;
    public class X509TrustForMSL implements X509TrustManager {
    /*
    * The default X509TrustManager returned by SunX509. We'll delegate
    * decisions to it, and fall back to the logic in this class if the
    * default X509TrustManager doesn't trust it.
    */
    X509TrustManager sunJSSEX509TrustManager;
    X509TrustForMSL() throws Exception {
    // create a "default" JSSE X509TrustManager.
    KeyStore ks = KeyStore.getInstance("JKS");
    ks.load(new FileInputStream("D:\jssecacerts"),
    "changeit".toCharArray());
    TrustManagerFactory tmf =
    TrustManagerFactory.getInstance("SunX509");//, "SunJSSE"
    tmf.init(ks);
    TrustManager tms [] = tmf.getTrustManagers();
    /*
    * Iterate over the returned trustmanagers, look
    * for an instance of X509TrustManager. If found,
    * use that as our "default" trust manager.
    */
    for (int i = 0; i < tms.length; i++) {
    if (tms[i] instanceof X509TrustManager) {
    sunJSSEX509TrustManager = (X509TrustManager) tms[i];
    return;
    }
    }
    /*
    * Find some other way to initialize, or else we have to fail the
    * constructor.
    */
    throw new Exception("Couldn't initialize");
    }
    /*
    * Delegate to the default trust manager.
    */
    public void checkClientTrusted(X509Certificate[] chain, String authType)
    throws CertificateException {
    try {
    sunJSSEX509TrustManager.checkClientTrusted(chain, authType);
    } catch (CertificateException excep) {
    // do any special handling here, or rethrow exception.
    }
    }
    /*
    * Delegate to the default trust manager.
    */
    public void checkServerTrusted(X509Certificate[] chain, String authType)
    throws CertificateException {
    try {
    sunJSSEX509TrustManager.checkServerTrusted(chain, authType);
    } catch (CertificateException excep) {
    /*
    * Possibly pop up a dialog box asking whether to trust the
    * cert chain.
    */
    }
    }
    /*
    * Merely pass this through.
    */
    public X509Certificate[] getAcceptedIssuers() {
    return sunJSSEX509TrustManager.getAcceptedIssuers();
    }
    }

    Eclipse测试没问题,但是发布到WebSphere中报错,说不支持SunJSSE,查了半天,原来IBM不支持sun公司的jdk中的jsse.jar包,网上说有自己添加的,也有说把证书加入哪里的,或许因为本人愚笨,搞了大半天,p用没有,最后终于悟得以下方法:

    public static void main(String args[]) throws Exception{
    // 创建SSLContext对象,并使用我们指定的信任管理器初始化
    SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");

    sslContext.init(null, new TrustManager[] {new TrustAnyTrustManager()},new java.security.SecureRandom());
    // 从上述SSLContext对象中得到SSLSocketFactory对象
    SSLSocketFactory ssf = sslContext.getSocketFactory();
    // 创建URL对象
    URL myURL = new URL("https://211.144.221.138/mslws/Services/rsa/RsaWebService.svc/security/validateagencyqualification");

    String businessCode = "SH30580";
    GenerateXml xml = new GenerateXml();
    String xmlContent = xml.writeXmlString(businessCode);

    // 创建HttpsURLConnection对象,并设置其SSLSocketFactory对象
    Proxy proxy = new Proxy(Proxy.Type.HTTP,new InetSocketAddress("10.38.194.30", 8080));
    HttpsURLConnection httpsConn = (HttpsURLConnection) myURL.openConnection();
    httpsConn.setRequestProperty( "Proxy-Authorization", "Basic " + new sun.misc.BASE64Encoder().encode("dajiang:Abcd1234".getBytes()) );
    httpsConn.setSSLSocketFactory(ssf);
    httpsConn.setHostnameVerifier(new TrustAnyHostnameVerifier());
    // 以POST方式提交
    httpsConn.setRequestMethod("POST");
    // 设置连接输出
    httpsConn.setDoInput(true);
    httpsConn.setDoOutput(true);
    // Post 请求不能使用缓存
    httpsConn.setUseCaches(false);
    httpsConn.setRequestProperty("Content-Type","application/xml");
    // httpsConn.connect();

    //获取输出流
    OutputStream os = httpsConn.getOutputStream();
    // // 设置输出流字符集
    os.write(xmlContent.getBytes("UTF-8"));
    os.flush();
    os.close();

    // 取得该连接的输入流,以读取响应内容
    InputStreamReader insr = new InputStreamReader(httpsConn.getInputStream());
    // 读取服务器的响应内容并显示
    int respInt = insr.read();
    while (respInt != -1) {
    System.out.print((char) respInt);
    respInt = insr.read();
    }

    }

    /*
    * 用于连接https使用
    */
    private static class TrustAnyTrustManager implements X509TrustManager {
    public void checkClientTrusted(X509Certificate[] chain, String authType)throws CertificateException {
    }

    public void checkServerTrusted(X509Certificate[] chain, String authType)throws CertificateException {
    }

    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
    return new java.security.cert.X509Certificate[] {};
    }

    public void checkClientTrusted(java.security.cert.X509Certificate[] arg0, String arg1)
    throws java.security.cert.CertificateException {
    }

    public void checkServerTrusted(java.security.cert.X509Certificate[] arg0, String arg1)
    throws java.security.cert.CertificateException {
    }
    }

    private static class TrustAnyHostnameVerifier implements HostnameVerifier {

    public boolean verify(String hostname, SSLSession session) {
    return true;
    }
    }

    按这种方法,终于链接成功,大石头落地~!

  • 相关阅读:
    Java基础教程:对象比较排序
    算法:深度优先搜索
    微信小程序开发:学习笔记[5]——JavaScript脚本
    微信小程序开发:学习笔记[4]——样式布局
    设计模式:学习笔记(8)——装饰器模式
    设计模式:学习笔记(7)——原型模式
    设计模式——单例模式解析
    玩转Android之数据库框架greenDAO3.0使用指南
    Android开发工具——Android Studio调试技巧
    VR开发的烦恼——范围限制
  • 原文地址:https://www.cnblogs.com/Mr-Rocker/p/4042453.html
Copyright © 2011-2022 走看看