webservice高级,安全(附带实例)

最简单的安全方案

J2EE容器端的WebService,是由Servlet来提供的,以Metro为例,所有的webservice请求都是由com.sun.xml.ws.transport.http.servlet.WSServlet处理的。所以,最简单的方法,便是将安全问题交给web容器来处理。比如,使用HTTPs保证消息传输安全,使用BA来保证认证与授权。

使用此种方案,首先需要配置容器,开启SSL端口,如http://my.oschina.net/xpbug/blog/204794#OSC_h3_5 一段展示了如何开启tomcat的SSL端口 。其次,需要配置容器BA认证与授权机制,如http://my.oschina.net/xpbug/blog/198765,文章展示了如何配置tomcat容器的安全 。前面均是针对容器所做的配置,针对WebServiceClient,我们还需要按照BA的格式,将用户名和密码放置到HTTP header中。

下面一段代码展示了如何将用户名和密码以BA的形式放入HTTP header中。

public class WsClient{
 
    //Because of BA, we can't parse wsdl "http://localhost:8080/WebServiceExample/user.wsdl" directly
    //save it as local file, and parse it
    private static final String WS_URL = "file:c://user.wsdl";
 
    public static void main(String[] args) throws Exception {
 
    URL url = new URL(WS_URL);
        QName qname = new QName("http://mycompany.com/""TestImplService");
 
        Service service = Service.create(url, qname);
        Test port = service.getPort(Test.class);
 
        //add username and password for container authentication
        BindingProvider bp = (BindingProvider) port;
        bp.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "mkyong");
        bp.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "123456");
 
        System.out.println(port.doSth());
    }
}

最简单的安全存在着很多缺陷,无法发挥webservice的全部特性,缺陷有下:

  1. 方案依托的是HTTP容器,要求SOAP必须通过HTTP传输,且依托HTTP heander。这使SOAP消息无法独立。如果想使用SMTP发送SOAP消息,需要重新设计安全机制。

  2. HTTPS的非对称秘钥,使得SOAP消息只能是两个端之间传输,无法被直接转发到第三端,除非经过处理,重新解密然后用第三端证书加密。这很混乱。

  3. HTTPS只保证了传输安全,被接收以后,就无法再保证安全。SOAP消息在Proxy端解密,再被转发之前,被恶意修改。如何保证SOAP消息在中转的时候不会被修改,甚至不被解析泄露内容也是安全的一个重要性。

  4. SOAP消息可能会分发给各种服务商,我们只希望消息中的某一部分可以被相应的服务商所解析,其它部分都是加密的。这需要消息中的需要部分加密,且可以使用不同的加密算法。

综上所述,最简单的安全方案可以用在消息并不敏感的服务商中,如果针对银行,那还是需要更加复杂的安全方案。

专门针对WebService的安全方案

Metro实现了WS-Security,WS-SecureConversation和WS-Trust等设计安全的规范。其复杂性自不必说,我对此也是一知半解。需要深入了解的时候,还是需要去读文档说明。但安全,总是无外乎这么一个过程:

1, 签名,接收端可以验证签名,以检验消息是否被修改过。

2, 加密,对消息整体进行加密,保证消息不会泄露。任何中介都无法解析原始消息。如果有恶意中介篡改加密后的消息,但它却给出正确的加密签名。使用第一项便可验证处消息被篡改过。

3, 用户名与密码验证。在传输过程中,将用户名密码放入header中,再进行加密。服务器端可以拿到用户密码,并加以验证。

4, 使用证书。

WS-Security可以不依赖传输协议,完全实现SOAP消息的自包含式安全,它对SOAP消息体签名,把签名放到SOAP header中,可以把用户信息放入SOAP header中,最后可以对部分SOAP消系进行加密。WS-Security很复杂,它也提供了非常繁多的安全解决机制。不过好在NetBeans帮我们简化了这部分的开发。

首先看下,Metro提供了多少安全组合方案:

服务端:

客户端

各种组合的解释可以在这个网站获得:https://metro.java.net/guide/ch12.html#ahicu 

我们不可能在真正使用之前全部掌握所有的安全机制,只可能了解每一个机制的特点,当真正需要用到时,再一边看文档,一边实现。

接下来,我选取上面安全机制中的第一个,来做一个实验。使用Username Authentication with Symmetric Key (UA)。

对称密钥用户认证

原理

原英文名叫Username Authentication with Symmetric Key (UA),我把它翻译成使用对称密钥及用户认证的安全机制

作为WS-Security安全机制的一种,此种机制是一种最常见的加密方法。其效率要比非对称加密算法要高很多。它的原理如下:

  1. 服务器端需要先生成一对公钥和密钥。

  2. 客户端安装服务器的公钥。

  3. 当客户端发起请求的时候,其必须输入用户名和密码。

  4. 客户端动态随机生成一个对称密钥。

  5. 客户端使用服务器公钥,加密对称密钥,放到SOAP头中。

  6. 客户端使用对称密钥,加密用户名,密码,放到SOAP头中。

  7. 客户端使用对称密钥,加密消息体,放到SOAP体中。

  8. 客户端发出SOAP消息。

  9. 服务器接收SOAP消息,使用密钥,可以解析出对称密钥。此时,服务器和客户端共享了对称密钥。

  10. 服务器使用对称密钥解析用户名,密码,消息体。 先验证账户,再执行消息。

  11. 服务器使用对称密钥加密返回的消息。

接下来,我将对此做实现。

必备软件

最新NetBeans IDE.

Glassfish4

JDK7

由于Glassfish4本身就自带Metro2.3,比Tomcat更容易使用,所以选择Glassfish4作为服务器。而NetBeans又是开发Metro WebService的利器。

创建账户

向Glassfish中添加账号。启动Glassfish, 打开控制台:http://localhost:4848/ 

展开Configurations->Default Config -> Security ->Realms->File

在此页面上,点击Manage Users按钮,添加一个用户:{name: xpbug,  group: test, password: test}

确保Glassfish使用的是File Realm做认证。

创建服务器端数字证书

Glassfish的keystore和trustStore在domain下的config目录中,例如C:\glassfish4\glassfish\domains\domain1\config。

其中keystore为keystore.jks, 而trustStore为cacerts.jks. 对于服务器端,我们不需要去管trustStore。

在glassfish keystore目录下面,使用命令,创建证书:

keytool -genkey -alias myWebService -keyalg RSA -keysize 1024 -keystore keystore.jks -validity 365

keystore.jks的默认密码为changeit

注意,在填写First and Last name或者是Common name的时候,需要填写网站的域名。否则证书无法工作。

注意,生成数字证书的密码必须使用跟keystore相同的密码,这是glassfish的一个limitation,否则,glassfish会启动失败。这里有解释:http://weblogs.java.net/blog/kumarjayanti/archive/2007/11/ssl_and_crl_che.html 

导出证书

需要将服务器端的数字证书导出,证书中含有公钥。此证书将为客户端所用。在服务器的keystore目录下,运行命令:

keytool -export -alias myWebService -file my.cer -keystore keystore.jks

创建WebService

使用NetBeans创建一个Java Web项目,取名为Test。

然后右键点击项目,创建一个Web Service。取名为Say。SEI中将默认产生一个hello方法。我们就用它做实验。

右键点击生成的webservice,选择Edit Web Service Attributes. 按照下图填写:

点击Keystore按钮,在弹出的对话框中填写你的keystore,密码,证书alias,以及证书的密码:

右键点击项目,点击deploy。

访问http://localhost:8080/Test/Say 看WebService是否部署成功。运行http://localhost:8080/Test/Say?Tester ,网站会报告webservice被加密,无法运行tester的信息。

创建客户端

在NetBeans中,创建一个Java项目。然后再项目中,创建Web Service Client。WSDL的地址为 http://localhost:8080/Test/Say?wsdl

当项目编译完成以后,客户端endport的java 类已经完全在项目中了,接下来,在Library中加入Metro2

在main函数中调用endport。

public class JavaApplication1 {
    public static void main(String[] args) {
        Say port = new Say_Service().getSayPort();
        System.out.println(port.hello("test"));
    }
}

运行项目,会发现运行错误。SOAP header无法解析。

原因在于我还没有导入server的证书。

首先,服务器的证书my.cert导入到客户端的truststore中。使用命令:

keytool -import -alias myWebService -file my.cer -keystore d:/clientTrustStore.jks -storepass testit

将my.cer导入到我的truststore中,如果store不存在,则自动创建。

然后,在NetBeans中,右键点击客户端项目中的web service

在弹出的菜单中选择Edit Web Service Attributes. 在QoS面板下的Security一栏中,点击Truststore.

填写上刚刚创建好的truststore的信息。

接着,在用户栏中使用Glassfish Realm中的账号。

运行项目,这次可以看到:

Hello test !

在glassfish的domain.xml中,添加

<jvm-options>-Dcom.sun.xml.ws.transport.http.HttpAdapter.dump=true</jvm-options>

可以在log中看到SOAP消息的进出记录。

  ---[HTTP request]---
accept: text/xml, multipart/related
connection: keep-alive
content-length: 8202
content-type: text/xml;charset=utf-8
host: localhost:8080
soapaction: "http://my.com/Say/helloRequest"
user-agent: JAX-WS RI 2.2-hudson-740-

【SOAP message】

自己去查看,会发现所有的内容均被加密。

 webservice高级,安全(附带实例)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值