axis2实现HTTPs双向认证的几种方式

1、  重写transport Sender类并重定义axis2的配置文件。

参考http://www.cnblogs.com/SoYoung/archive/2012/04/08/Custom_SSL_in_Axis2.html

 

主要目的是需要实现一个SSLcontext(注:主要是实现自己的SSLProtocolSocketFactory,在getSSLContext方法里面使用下面方式构造一个SSLContent并返回,下面这段代码是写到了createSocket里面了,可以分开来)

SSLContext ctx = SSLContext.getInstance("SSL");
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
KeyStore ks = KeyStore.getInstance("JKS");
KeyStore tks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream("data/kclient.keystore"), CLIENT_KEY_STORE_PASSWORD.toCharArray());
tks.load(new FileInputStream("data/tclient.keystore"), CLIENT_TRUST_KEY_STORE_PASSWORD.toCharArray());
kmf.init(ks, CLIENT_KEY_STORE_PASSWORD.toCharArray());
tmf.init(tks);
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
return (SSLSocket) ctx.getSocketFactory().createSocket(DEFAULT_HOST, DEFAULT_PORT);

有了SSLContext后

可以按如下方式使用HttpClient
Protocol myhttps =new Protocol("https", new MySecureProtocolSocketFactory (), 443);
Protocol.registerProtocol("https", myhttps);
HttpClient httpclient=new HttpClient();

 

自定义transport Sender类(关键步骤)

    <transportSender name="https" class="com.**.**.common.MyHTTPTransport">

        <parametername="PROTOCOL">HTTP/1.0</parameter>

        <parametername="Transfer-Encoding">chunked</parameter>

    </transportSender>

 

创建java类MyHTTPTransport直接继承TransportSender,并且复制其中的方法。

在其中的writeMessageWithCommons方法中会使用到AbstractHTTPSender和HttpSender,同样的方法,继承并复制其中的方法创建MyAbstractHTTPSender和MyHttpSender类。

配置了自定义的处理类后,剩下的是如何传入定制的SSLcontext和如何在httpsender中使用它

 

在HttpSender中的getHostConfiguration方法中会看到这么一段话:(Axis2的开发人员很幽默)

// I assume the 90% case, or even 99% case will be no protocolhandler case.

        if (protocolHandler ==null) {

           config.setHost(targetURL.getHost(), port, targetURL.getProtocol());

        } else {

           config.setHost(targetURL.getHost(), port, protocolHandler);

        }

 

如此则可以将上面自定的protocol(包含配置好的sslcontext)传进来即可,通过configContext传入(注:下面这段代码写在构建stub时,可以把keystore文件路径的设置也提前到这里来)

         String path =FileUtil.getWebInfPath();

           ConfigurationContext configContext = ConfigurationContextFactory

                   .createConfigurationContextFromFileSystem(path, path +"conf/axis2.xml");

           AuthSSLProtocolSocketFactory sslProtocalFactory = newAuthSSLProtocolSocketFactory(vdiConfig.getCertStream(),vdiConfig.getPk());

           ProtocolSocketFactory socketFactory = (ProtocolSocketFactory)sslProtocalFactory;

           Protocol authhttps = new Protocol("https",socketFactory,443);

           configContext.setProperty("httpsProtocol", authhttps);

           vdistub = new VdsServiceStub(configContext,ItaURL);

 

然后在HttpSender中的getHostConfiguration方法中加入设置代码

 Protocol authhttps =(Protocol)msgCtx.getConfigurationContext().getProperty("httpsProtocol");

   protocolHandler = authhttps;

 

 

2、  直接使用rampart的配置方式

参考:http://blog.csdn.net/lifetragedy/article/details/7844589

下面是实际项目中使用的(当然隐藏了敏感字)

       <!-- 对此服务启用rampart模块 -->

       <module ref="rampart" />

 

      <parametername="OutflowSecurity">  

      <action>  

        <items>TimestampSignature</items>

       <timeToLive>60000</timeToLive>  

        <!-- user要跟证书上别名一致 -->

        <user>gsdfsdf</user>  

       <signaturePropFile>conf/client.properties</signaturePropFile>

<passwordCallbackClass>***.PWCBHandler</passwordCallbackClass>

        <signatureKeyIdentifier>X509KeyIdentifier</signatureKeyIdentifier>

      </action>  

</parameter>

 

org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin

org.apache.ws.security.crypto.merlin.keystore.type=pkcs12

org.apache.ws.security.crypto.merlin.keystore.password=888888

org.apache.ws.security.crypto.merlin.file=conf/client.p12

 

在代码中只需要指定axis2.xml配置文件,其他什么都不用动了:

                   String path = FileUtil.getWebInfPath();

            ConfigurationContextconfigContext = ConfigurationContextFactory

                    .createConfigurationContextFromFileSystem(path,path + "conf/axis2.xml");

           configContext.setProperty(HTTPConstants.REUSE_HTTP_CLIENT, Boolean.TRUE);

 

3、  重写org.apache.ws.security.crypto.provider的方式。

这种方式是第2种的变种版本,某些特殊的情况如将priKey和证书存到数据库中的情况可以使用。

publicclass CustomizableCrypto implements Crypto

{

    /**

     * 构造X509格式证书的工厂变量

     */

    private CertificateFactory certFact;

 

    /**

     * 获取构造X509格式证书的工厂变量(单例模式)

     *

     * @return证书工厂变量

     */

    publicsynchronizedCertificateFactory getCertificateFactory()

    {

        if (certFact == null)

        {

            try

            {

                certFact =CertificateFactory.getInstance("X.509");

            }

            catch(CertificateException e)

            {

                if (logger.isErrorEnable())

                {

                    logger.error("Fail to get CertificateFactory");

                }

            }

            returncertFact;

        }

 

        returncertFact;

    }

 

    public PrivateKeygetPrivateKey(String keyName, String passwrod)

    {

         PEMReader pemIn;

        ByteArrayInputStreampemByteIn = new ByteArrayInputStream(getprivatekey(keyName));

        pemIn = new PEMReader(newInputStreamReader(pemByteIn));

return ((KeyPair) pemIn.readObject()).getPrivate();

 

    }

 

    public X509Certificate[]getCertificates(String keyName)

    {

        X509Certificate[] certList= new X509Certificate[1];

        // psql中取出证书并转换为X509格式证书

        CertificateFactory cf = null;

        X509Certificate cert = null;

        cf = getCertificateFactory();

        ByteArrayInputStream bais =new ByteArrayInputStream(getCertificate(keyName));

        cert = (X509Certificate)cf.generateCertificate(bais);

        certList[0] = cert;

        return certList;

    }

   

    其他方法空实现....

}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值