一种简单的web service服务安全策略

继上两篇([url=http://redhacker.iteye.com/blog/1444508]jdk6下开发webservice示例[/url],利用[url=http://redhacker.iteye.com/blog/1447248]soapui和jdk API访问webservice[/url])关于如何创建并调用web service的博客后,我一直还想写点关于web service相关的内容,一直忙其他的事,拖到今天,终于要想写一点。

对于web service,通过前面两篇博客,我们已经能够很方便的创建一个web service,并调用它,对于初学web service技术的同学来说,是个良好的开端。但是,很快大家会提出一个问题:这样的web service如何保证它的安全性呢?今天我就向大家介绍一种比较简单的方式。

1、这种ws安全的原理示意图

为了让大家清楚的了解篇文章想要讲述的WS安全原理,我粗略的画了一个图。后面叙述我会结合该图进行讲述。

[img]http://dl2.iteye.com/upload/attachment/0086/4284/83aa33b0-ec03-395e-9005-b688a9d481f6.jpg[/img]

2、让我们先看看Tomcat2中App1的WS要如何通过容器认证保护起来

在web.xml里,我们加入如下代码,对ws进行保护:

[code]
<security-role>
<description>role for acess the WS api</description>
<role-name>WSAdmin</role-name>
</security-role>
<security-constraint>
<web-resource-collection>
<web-resource-name>web service api</web-resource-name>
<url-pattern>/ws/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>WSAdmin</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
</login-config>
[/code]

在tomcat/conf/tomcat-user.xml,定义保护起来的WS对应的角色和用户,如下所示

[code]
<tomcat-users>
<role rolename="WSAdmin"/>
<user username="redhacker" password="11111111" roles="WSAdmin"/>
</tomcat-users>
[/code]

从上面代码可以看到只要URL为/ws/*的WS服务均需要进过容器认证,认证的约束是:必须是WSAdmin下的用户,这些代码片段相信大家很容易理解。

那么我们的WS是如何编写的?如果这个还不会的话,请大家补习“[url=http://redhacker.iteye.com/blog/1444508]jdk6下开发webservice示例 [/url]”

3、通过上面的的机制,WS服务被容器认证保护了起来!这是大家通过浏览器访问这个WS服务,浏览器将会提示您输入用户名和密码,如下图所示:

[img]http://dl2.iteye.com/upload/attachment/0086/4313/eea1ed0f-1999-3980-9788-a255a87d4c37.png[/img]

输入正确的用户名和密码(这个用户名和密码是我们在上一个步骤中配置好的,并且是属于WSAdmin这个角色的),你将会访问到这个WS,如下图所示:

[img]http://dl2.iteye.com/upload/attachment/0086/4315/2d70fec5-adc0-33d4-b918-07e9ca7da6c9.png[/img]

这时候,我们就可以认为我么的WS服务被有效的保护起来了!

4、再来让我们先看看APP1中的ws client的代码:
[code]
public class HelloServiceTest {

// 调用WS
public static String testHelloService(String name) throws Exception,
IOException {

Authenticator.setDefault(new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("redhacker", "11111111".toCharArray());
}
});

// 构建请求报文
StringBuffer sendMsgBuffer = new StringBuffer(
"<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:jav=\"http://www.javaedu.com\">");
sendMsgBuffer.append("<soapenv:Header/>").append("<soapenv:Body>")
.append("<jav:hello>").append("<arg0>").append(name)
.append("</arg0>").append("</jav:hello>")
.append("</soapenv:Body>").append("</soapenv:Envelope>");
String sendMsg = sendMsgBuffer.toString();

// 开启HTTP连接ַ
URL url = new URL(Util.HELLO_WS_URL);
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();

// 设置HTTP请求相关信息
httpConn.setRequestProperty("Content-Length",
String.valueOf(sendMsg.getBytes().length));
httpConn.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
httpConn.setRequestMethod("POST");
httpConn.setDoOutput(true);
httpConn.setDoInput(true);

// 进行HTTP请求
OutputStream outObject = httpConn.getOutputStream();
outObject.write(sendMsg.getBytes());

// 关闭输出流
outObject.close();

// 获取HTTP响应数据
InputStreamReader isr = new InputStreamReader(
httpConn.getInputStream(), "utf-8");
BufferedReader inReader = new BufferedReader(isr);
StringBuffer result = new StringBuffer();
String inputLine;
while ((inputLine = inReader.readLine()) != null) {
result.append(inputLine);
}

// 打印HTTP响应数据
System.out.println(result);

// 关闭输入流
inReader.close();
isr.close();
return result.toString();
}
[/code]

上面的代码与前面博客中提到WS调用方式没什么两样,唯一不同的是,这段代码中加入了如下认证代码:

[code]
Authenticator.setDefault(new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("redhacker", "11111111".toCharArray());
}
});
[/code]

上面这段代码就是通过程序访问WS前需要进行的认证,我们看看上面客户端程序执行的效果!通过执行客户端,得到如下报文信息:

[code]
<?xml version="1.0" ?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><ns2:helloResponse xmlns:ns2="http://www.javaedu.com"><return>Hello,jack</return></ns2:helloResponse></S:Body></S:Envelope>
[/code]

当我们从ws client中删除上述认证代码,执行将产生如下错误:
[code]
Exception in thread "main" java.io.IOException: Server returned HTTP response code: 401 for URL: http://127.0.0.1:8080/ws/HelloServicePort?wsdl
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1436)
at com.je.ws.client.HelloServiceTest.testHelloService(HelloServiceTest.java:56)
at com.je.ws.client.HelloServiceTest.main(HelloServiceTest.java:75)
[/code]

总结:

通过上除的一种机制,我们就可以有效的保护我们的WS服务了!当然,关于WS安全不仅仅是上述一种方法,我将在后续的博客中介绍其他的方式。值得需要说明的是,上述机制在weblogic上,会有一些问题,大家可以看一下这个(https://forums.oracle.com/message/10746741?#10744741)帖子,或许是weblogic上的一个bug,我们期待weblgic能够解决这个问题。


提示:

由于APP2较大,压缩了两个分包,大家解压的使用使用解压工具7-zip,将附件中的两个文件名改为ws_test_sample.zip.001,ws_test_sample.zip.002方可解压成功!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值