cxf走https加密实现安全的webService

一、加密原理

    假设我已经使用cxf构建了基于密码验证的webService ,此时只有给出正确的用户名和密码才能调用我的webservice,但这个webservice还不是绝对安全,因为走的是http,如果中间有人抓了http包,他看到明文的用户名密码,他就可以假装自己是正常用户,来调用我的webservice。为了防止信息已明文传送,再使用ssl加密,走https。   

    公钥和私钥是一对数字。公钥加密的东西只有私钥才能解密。把公钥公开分发给任何人,当他们要同我们联系时,把信息用公钥加密,此时只有拥有私钥的人才能解密。如果有人截获了信息,但他没有私钥,他也不知道发了什么。公钥和私钥是对称的,服务器返回数据时也可以用私钥加密,客户端用公钥来验证是否是服务端返回的数据,这样就保证了安全性。

    alice使用随机数生成一对公钥私钥,分发公钥出去。

cxf走https加密实现安全的webService

bob要给alice发送信息,就用公钥加密,Alice收到后用私钥解密就可以看到了

cxf走https加密实现安全的webService

alice返回信息的时候,也可以用私钥加密,顺便生成签名。bob用公钥解密就可以验证是否是alice返回的数据。

cxf走https加密实现安全的webService

    证书除开包含公钥外,还有发布公钥的人的信息。有密钥对就可以生成证书。不过这个是自己生成的,并没有去权威机构认证,所以浏览器访问的时候会报安全警告。从网上获取到别人的证书,就可以拿到他的公钥。

java提供了工具来生成密钥对、证书。

#生成keystore文件,既密钥文件 730天。还可以填些个人信息,
keytool -genkeypair -validity 730 -alias myservicekey \
     -keystore serviceKeystore.jks -dname "cn=hutao,ou=eloan,o=wits,l=wuhan,c=cn" \
     -keypass xiaotaozi -storepass xiaotaozi
keytool -genkeypair -validity 730 -alias myclientkey -keystore clientKeystore.jks \
     -keypass ckpass -storepass cspass

#导出服务端的证书
keytool -export -rfc -keystore serviceKeystore.jks -alias myservicekey \
     -file MyService.cer -storepass tianyixiaodai
#把服务端导入客户端的信任库
keytool -import -noprompt -trustcacerts -file MyService.cer -alias myservicekey \
     -keystore clientKeystore.jks -storepass cspass
#导出客户端的证书 
keytool -export -rfc -keystore clientKeystore.jks -alias myclientkey -file MyClient.cer \
     -storepass cspass
keytool -import -noprompt -trustcacerts -file MyClient.cer -alias myclientkey \
     -keystore serviceKeystore.jks -storepass tianyixiaodai

    我们不关心服务器是否是自己的服务器,所以不需要给客户端也生成证书,上面的命令只执行服务器端的。如果是双向认证,则客户端也要生成,且相互添加信任,上面的命令全部要执行。
    -keystore 和 -storepass分别是当前密钥的密码和当前密钥文件的操作密码,最好设置一样,我这里不一样的话,tomcat无法部署。keystore就是密码,storepass就是你有这个密码,才能读取这个密钥文件。

    如果我们是调用别人的webservice,可以用浏览器打开wsdl,下载证数,利用import命令生成一个客户端密钥文件。然后用该密钥文件就可以调用了。

二、发布走https加密的webservice

    主要是要配置tomcat。首先利用上面的第一条命令生成密钥文件serviceKeystore.jks 。首先打开tomcat, server.xml

<Connector SSLEnabled="true" clientAuth="false" 
   keystoreFile="C:\\Users\\samsung\\serviceKeystore.jks" keystorePass="xiaotaozi" 
   maxThreads="150" port="8443" protocol="org.apache.coyote.http11.Http11Protocol" 
   scheme="https" secure="true" sslProtocol="TLS"/>

打开8443端口上的连接器,如果有需要ssl的连接进来,tomcat会自动转发到这个端口。 keystorePass就是密钥文件的操作密码。我这里sslProtocol是TLS。 clientAuth=false表示只需要单向认证,不需要客户端也给我他的公钥,如果只是加密,单项已经足够。

   然后配置tomcat web.xml,设置哪些url需要使用https。

    <login-config>
        <auth-method>CLIENT-CERT</auth-method>
        <realm-name>Client Cert Users-only Area</realm-name>
    </login-config>
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>SSL</web-resource-name>
            <url-pattern>/witsws/*</url-pattern>
        </web-resource-collection>
        <user-data-constraint>
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
    </security-constraint>

因为我的webService地址都以witsws开头,所以设置成这样。

启动tomcat,访问8443端口,会出现,证书不被信任的提示信息,表示已经部署成功。如果用http访问witsws下的路径会自动被转成https。

三、配置cxf

    以调用上面的webservice为例。 在浏览器中下载证书。假设证书保存的名字为MyService.cer运行下面的命令

keytool -import -noprompt -trustcacerts -file MyService.cer -alias myservicekey \
     -keystore clientKeystore.jks -storepass cspass

    此时会要求你输入自己的密码,我输123456,并生成本地的密钥文件。

    在cxf客户端配置自己的密钥文件之后就可以访问对方的webservice。写一个cxf-client-test.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:jaxws="http://cxf.apache.org/jaxws"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:http="http://cxf.apache.org/transports/http/configuration"
       xmlns:sec="http://cxf.apache.org/configuration/security"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans.xsd
        http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
           http://cxf.apache.org/transports/http/configuration 
      http://cxf.apache.org/schemas/configuration/http-conf.xsd
           http://cxf.apache.org/configuration/security 
        http://cxf.apache.org/schemas/configuration/security.xsd">
 
    <jaxws:client id="testCamClient"
                  serviceClass="com.xxx.wesb.cam.webservice.CamService"
                  address="https://127.0.0.1:8443/xxx-esb/witsws/camService"/>
                  
    <http:conduit name="*.http-conduit"> <!--这里简便配法,详细的参考官方文档-->
        <!--注意这里的secureSocketProtocol 要和tomcat一模一样-->
        <http:tlsClientParameters disableCNCheck="true" secureSocketProtocol="TLS">
            <!--自己的密钥 单向调用别人的时候,这里不用配置 如果是双向的,配上自己的
            <sec:keyManagers keyPassword="123456"> 
                <sec:keyStore type="JKS" password="123456" 
                    file="C:\\Users\\samsung\\clientKeystore.jks" /> 
            </sec:keyManagers>-->
            
             
            <!--这里填写我们刚刚生成的密钥文件--> 
            <sec:trustManagers> 
                <sec:keyStore type="JKS" password="123456" 
                   file="C:\\Users\\samsung\\clientKeystore.jks" /> 
            </sec:trustManagers>
                
           <sec:cipherSuitesFilter> 
                <sec:include>.*_EXPORT_.*</sec:include> 
                <sec:include>.*_EXPORT1024_.*</sec:include> 
                <sec:include>.*_WITH_DES_.*</sec:include> 
                <sec:include>.*_WITH_NULL_.*</sec:include> 
                <sec:exclude>.*_DH_anon_.*</sec:exclude> 
            </sec:cipherSuitesFilter> 
        </http:tlsClientParameters> 
    </http:conduit>
</beans>

然后写个单元测试,就可以调用了

public class TestCreditQuery  extends TestCase  {

    public void testCreditQuery() {
        ApplicationContext app = 
             new ClassPathXmlApplicationContext("testwsconfig/cxf-client-test.xml");
        CamService ws = (CamService) app.getBean("testCamClient");
        String xml = ws.service("xxxxxx");
        System.out.println(xml);
    }
}

如果报错,fatal alert handshake 可以判定是相互的密钥没法配对,可能是版本、或者协议不匹配。也可能没相互导入信任。如果是sec的那些类直接没法实例化,基本是密钥文件错误,或者密钥文件操作密码写错。


如果是双向验证,则在客户端也生成证书,修改tomcat连接器设置,修改cxf,双方都加上对方和自己的密钥文件。

你可能感兴趣的:(加密,webservice,CXF,https)