如何使用 JDeveloper 10.1.3 保护和测试 Web 服务
作者:Susan Duncan 和 Colin Maxwell,Oracle Corporation
2006 年 5 月
概述
该方法文档介绍了如何使用 JDeveloper 10.1.3 开发、保护和测试 Web 服务。JDeveloper 提供了一个测试环境,用于保护自签名密钥对的完整性以及加密细节,并将其添加到服务和代理中,从而确保服务由经过验证的用户使用、在传输过程中没有被篡改并且无法被“中间人”攻击读取。
Sun 的 Keytool 实用工具用于在密钥存储器中创建 RSA 自签名证书,以测试服务的安全性。
JDeveloper 用于将受保护服务和密钥存储器部署到 OC4J。要维护密码安全性,需要使用 OC4J 控制台为密钥存储器添加密码。JDeveloper 用于创建安全代理来测试运行中的受保护服务。最后,使用 HTTP Analyzer,开发人员可以查看服务器收发的经过签名和加密的 SOAP 消息。
步骤
前提条件
- 安装了 JDeveloper 10g (10.1.3)
- 启动了 Oracle Application Server Containers for J2EE (OC4J) (<JDEV_HOME>\jdev\bin\start_oc4j.bat)
如果提示输入密码,则输入 welcome。在您输入密码时(通常默认为
welcome),不显示任何内容。.
观察命令窗口中的结果,直到您看到消息“Oracle Containers for J2EE 10g (10.1.3.0.0) initialized”。
然后您可以最小化窗口,但不要关闭它
- 到正在运行的 OC4J 的 JDeveloper 连接:
- 单击 Connections 选项卡(如果 Connections 选项卡不可见,请从菜单中选择 View > Connection Navigator)。
- 右键单击 Application Server 节点,并从上下文菜单中选择
New Application Server Connection。
- 如果显示 Create Application Server Connection 向导的 Welcome 页面,则单击
Next。
- 在此向导的 Type 页面上,输入连接名称
oc4j_local,然后单击
Next。
- 在向导的 Authentication 页面上,输入密码
welcome(或最初启动 OC4J 时使用的任何密码)并选择 Deploy Password,然后单击 Next。
- 在向导的 Connection 页面上,单击
Next。
- 在向导的 Test 页面上,单击 Test Connection。在测试之后,Status 消息应显示 Success!。(如果显示了错误消息,则单击 Back,并更正您输入的连接信息。 )
- 单击
Next,然后单击
Finish
创建密钥存储器
在本例中,我们使用 Sun 的
keytool 实用工具通过
RSA 算法创建了一个包含 2 个自签名证书的密钥存储器
在新的密钥存储器中创建用于 sam 的密钥
- 打开一个命令提示符
- 导航到
<JDEV_HOME>\jdk\bin
- 输入以下代码,在名为
mytestkeystore 的新密钥存储器(位于
c:\temp)中为
Sam Moore 创建一个密钥。适当地更改位置
keytool -genkey -dname "CN=Sam Moore, OU=samDept, O=samOrg, L=samHome, S=Florida, C=US" -keyalg RSA -sigalg Sha1WithRSA -keystore c:\temp\mytestkeystore.jks -alias sam
- 输入密钥存储器密码:
mytestkeystore
- 输入用于 sam 的密钥密码:
sampwd
在同一密钥存储器中添加用于 dave 的密钥
- 输入以下代码,在
mytestkeystore 中为
Dave Prater
创建一个密钥。
如上所示更改位置
keytool -genkey -dname "CN=Dave Prater, OU=daveDept, O=daveOrg, L=daveHome, S=Georgia, C=US" -keyalg RSA -sigalg Sha1WithRSA -keystore c:\temp\mytestkeystore.jks -alias dave
- 输入密钥存储器密码:
mytestkeystore
- 输入用于 dave 的密钥密码:
davepwd
查看生成的密钥存储器的内容
- 输入以下代码,以显示密钥存储器的内容
keytool -list -v -keystore c:\temp\mytestkeystore.jks
- 输入密钥存储器密码:
mytestkeystore
有关使用 Keytool 的更多详细信息,请参见上面的链接
创建空白应用程序和项目
- 打开 New Gallery,方法是选择
File,然后选择
New。
- 在 New Gallery 的 Categories 树中,选择
General。
-
在 Items 列表中,双击
Application。
- 在 Create Application 对话框中,输入
WSSecurityDemo 作为应用程序名并单击 OK
- 在 Create Project 对话框中,输入
Server 作为项目名并单击 OK
创建 Java 类并将其发布为 Web 服务
创建 Java 类
- 打开 New Gallery,方法是选择
File,然后选择
New
- 在 New Gallery 的 Categories 树中,选择
General
- 在 Items 列表中,双击
Java Class
- 在 Create Java Class 对话框中,输入
SimpleWSImpl 作为类名并单击 OK
- 在源代码编辑器中,将以下代码添加到 Java 类
public String echoMe(String s) {
return s;
}
创建 Web 服务
- 在 Application Navigator 中,使用 SimpleWSImpl.java 的上下文菜单选择
Create J2EE Web Service
- 选择 J2EE 1.4 (JAX-RPC) Web Service
- 接受其他所有默认设置,并单击
Finish 生成 Web 服务
保护 Web 服务
- 在 Application Navigator 中,使用 MyWebService1 上下文菜单中的
Secure Web Service
- 在 Web Services Editor 的
Security 页上,单击
Ports 下的
MyWebService1SoapHttpPort 复选框
- 接受该页上的 Authentication、Integrity 和 Confidentiality 默认设置
该页设置该服务的 Port 的整体安全性配置文件:
1. Authentication — 将使用应用程序用户名/密码来验证该服务由经过授权的用户使用。也可以使用 X509n 证书或 SAML 进行身份验证。
2. Integrity and Confidentiality — 经过认证的用户将通过其密钥(在密钥存储器中)进行指定,从而对服务进行签名和加密
设置身份验证
身份验证:该服务的用户得到使用授权了吗?在本例中,将使用用户名/密码(而非 X509 证书)对用户进行身份验证
- 在 Security 下,选择 Authentication 页
- 接受默认设置
设置入站完整性
入站完整性:消息在从客户端传送到服务器的过程中遭到某种方式的篡改了吗?发送方的私钥用于对消息进行签名,而在接收方服务器上,发送方的公钥用于检查消息的完整性。
- 在
Security 下,选择
Inbound Integrity 页
- 选中
Creation Time Required in Timestamp 复选框。现在,所有复选框都应该选中
设置出站完整性
出站完整性:外发消息在从服务器传送到客户端的过程中遭到某种方式的篡改了吗?客户端的公钥用于对消息进行签名,而在接收方客户端上,客户端的私钥用于检查消息的完整性。
- 在
Security下,选择
Outbound Integrity 页
- 选中
Creation Time Required in Timestamp 复选框。现在,所有复选框都应该选中
添加密钥存储器选项
密钥存储器保留用户的认证密钥,并与在前面页面中作出的完整性和加密选择相关联
- 在
Security 下,选择
Keystore Options 页
- 对于
Keystore Path,浏览至
密钥存储器的位置
- 输入
Keystore Password,在本例中是
mytestkeystore
注意:访问密钥存储器和检索 Key 别名需要使用该密码
- 从下拉列表选择 Key Alias,在本例中 —
sam 用作
Signature Key Alias,而
dave 用作
Encryption Key Alias
注意,OC4J 需要一个单独密钥来进行签名和加密
设置出站机密性
出站机密性:消息在从服务器传送到客户端的过程中被他人读取了吗?用户的公钥用于对消息进行加密,而在接收方客户端上,客户端的私钥用于对消息进行解密
- 在 Security 下,选择
Outbound Confidentiality
- 设置 Public Key 的
Encryption Key Alias,在本例中是
dave
设置入站机密性
入站机密性:消息在从客户端传送到服务器的过程中被他人读取了吗?发送方的私钥用于对消息进行签名,而在接收方服务器上,发送方的公钥用于对消息进行解密
- 在
Inbound Confidentiality 下,接受默认设置
生成 oracle-webservices.xml
- 单击 OK 关闭 Web Services Editor,并生成 oracle-webservices.xml 文件
请注意,本文件现在包含安全设置,并且可以部署到 Web 服务
- 在编辑器中打开 oracle-webservices.xml 文件。
注意:密钥存储器的 <signature-key> 和 <encryption-key> 密码元素是空。要维护密码安全性,不应该将密码添加到该文件中。它们稍后将添加到部署的服务中
部署受保护的 Web 服务
- 在 Application Navigator 的 Resources 节点下,使用 Keystore.deploy 的上下文菜单打开 EAR Deployment Profile 的 Properties 对话框。也可以更改 Application Name(在本例中是
WSSecurityHowTo)
- 单击
OK 关闭
- 使用 Keystore.deploy 上下文菜单部署到
local_oc4j
(运行中的 OC4J 实例)
注意:Keystore.deploy 通过在密钥存储器属性文件(如上所示)中包含 WebServices.deploy 配置文件来部署密钥存储器和 Web 服务
- 在
Configure Application 对话框中,接受所有默认设置,单击
OK
设置服务的运行时安全性
添加身份验证的应用程序级用户名/密码
- 在浏览器中,为了打开 OC4J Enterprise Manager Application Server Control Console,请使用 URL
http://localhost:8888/em(假设 OC4J 实例正运行在本地主机上)
- 输入用户名和密码(默认为
oc4jadmin/welcome)进行登录
- 单击
Applications 选项卡查看部署的所有应用程序
- 单击到部署的应用程序的链接 —
WSSecurityHowTo
- 在 Application:WSSecurityHowTo 页中,单击
Administration 选项卡
- 单击
Security Provider 的
Go to Task 图标
- 在 Security Provider 页中,单击
Realms
- 单击
Users 添加新用户
注意,本例使用默认的 File-Based Security Provider
- 在 Users 页,单击
Create 添加新 User
- Username:
albert
- Password:
albert
- 单击
OK 创建
- 单击该链接:
Application:WSSecurityDemo-Server-WS
添加 Web 服务级密钥存储器密码信息
- 在 Application:WSSecurityHowTo-Server-WS 页中,单击
Web Services 选项卡
- 在 Web Services 选项卡上,单击
MyWebService1SoapHttpPort 链接
- 单击
Administration 选项卡查看
管理功能
注意,已经启用了 Security 条目
- 单击
Security 的
Edit Configuration 图标
- 单击
Keystore and Identity Certificates
- 添加一个密钥存储器名,在本示例中是
mytestkeystore
- 添加并确认密钥存储器密码,在本示例中是
mytestkeystore
- 添加并确认
签名密钥密码,在本示例中是
sampwd
- 添加并确认密钥存储器密钥密码,在本示例中是
davepwd
- 单击
OK 保存条目
创建受保护的客户端代理并测试受保护的 Web 服务
创建新项目
- 在应用程序中选择应用程序节点
- 使用上下文菜单创建一个
新项目
- 将项目命名为
Client
创建 Web 服务代理
- 在 A
pplication Navigator 中,选择
Client 项目
- 使用 Client 的上下文菜单打开
新图库
- 在 Categories > Business Tier 中,选择
Web Services
- 在 Items 下,选择
Web Service Proxy
- 从下拉列表选择
MyWebService1.wsdl。
Service Name 和 Mapping 文件信息将从服务细节填充
- 单击
Next
- 在第 2 步中选择
Run against a service deployed to an external server
注意:这使终点转到来自 WSDL 文件的部署的服务
- 接受所有其他的默认设置,并单击
Finish 生成代理
保护代理
- 使用 MyWebService1Proxy 的上下文菜单的
Secure Proxy
- 在向导的第 1、2、3 页上 — 接受默认设置。
注意:这会将客户端代理设置为与受保护服务相同的安全设置
- 在第 4 页上,添加
dave 的加密密钥别名
— 这也用在该服务中
- 在第 5 页上 — 接受默认设置。
注意:第 4 页和第 5 页将代理设置为收发加密的消息(正如服务所预期的)
- 在第 6 页上,添加密钥存储器路径、密码 (
mytestkeystore)、签名密钥别名 (
sam) 和加密密钥别名 (
dave)
注意:它们必须在服务器上映射这些设置
- 单击 Next 和
Finish 将 Proxy 安全设置生成到 MyWebService1SoapHttp_Stub.xml 文件中
将密码添加到代理
- 在 Application Navigator 中,选择
MyWebService1
Proxy
- 在 Structure Pane 中,将鼠标移到
MyWebService1SoapHttp_Stub.xml file 上,并确保该路径显示为
......\
client\runtime\MyWebService1SoapHttp_Stub.xml file
注意:生成的文件有两个副本,确保选择运行时版本。(另一个版本只位于 Application Navigator 中,不在运行时使用)
- 双击该文件打开它
- 在代码
编辑器中单击打开的文件
- 在 Structure Pane 中,扩展
port-info > runtime > security nodes
- 双击
key-store
- 添加该名称和 store-pass 属性值,在本示例中是
mytestkeystore
- 双击
signature-key
- 添加用于 sam 的 key-pass 值,在本示例中是
sampwd
- 双击
encryption-key
- 添加用于 dave 的 key-pass 值,在本示例中是
davepwd
- 在代码编辑器中,查看配置文件是否已经更新
- 全部保存
- 重新构建 Client 项目以便更新运行时文件
运行客户端
- 在
Code Editor 中,选择
MyWebService1SoapHttpPortClient.java 编辑器
- 将以下代码添加到
主方法
myPort.setUsername("albert");
myPort.setPassword("albert");
myPort.echoMe("testing secure service")
- 使用类的上下文菜单运行代理并调用服务
- 在登录窗口中,您应该看到返回
测试受保护的服务
使用 HTTP Analyzer 查看受保护的 SOAP 消息
- 从该菜单选择
Tools > Preferences > Web Proxy Browser,并关闭会干扰 HTTP Analyzer 的任何代理设置或异常
- 从该菜单选择
View > HTTP Analyzer
- 单击
绿图标启动 HTTP Analyzer
- 再次运行
MyWebService1HttpPortClient.java
注意:在 History 选项卡上,应该列出 Web 服务调用
- 选择调用的行并单击 HTTPAnalyzer 的
Data 选项卡
- 查看 SOAP 消息中发送的经过签名和加密的数据
- 单击红色椭圆形图标停止 HTTP Analyzer
结论
使用 JDeveloper,您可以创建、发布、保护 Web 服务,并将其部署为 WS-Security 标准。JDeveloper 可用作测试工具,能够在启用所有必需安全性的情况下调用部署的服务,以及在 HTTP Analyzer 中查看结果。不建议使用 JDeveloper 将受保护的 Web 服务部署到实际生产系统中。这通常由具有安全特权的管理员完成,或者通过使用 Oracle 的 Web Service Manager 集中管理服务的安全性和管理配置文件来完成。
故障诊断
| 症状
|
原因
|
解决方案
|
oracle.security.jazn.util.KeyStoreUtil loadKeystore
SEVERE:Error reading keystore data
java.io.IOException:Keystore was tampered with, or password was incorrect
|
client\runtime\MyWebService1SoapHttp_Stub.xml 文件的密码项错误。
|
重复这些步骤,将密码项细节添加到客户端部署描述符中。
请记住,使 XML 文件将自身复制到正确的运行时位置。
|
|
javax.xml.rpc.soap.SOAPFaultException:An invalid token was provided
at oracle.j2ee.ws.client.StreamingSender._raiseFault(StreamingSender.java:553)
或者在 OC4J 控制台窗口中:
2006-04-07 14:59:32.375 ERROR Invalid port config oracle.security.wss.config.SecurityPortImpl@fead77
06/04/07 14:59:32 java.lang.RuntimeException:Invalid port config :Error reading keystore data
06/04/07 14:59:32 at oracle.security.wss.interceptors.SecurityPortDescriptor.configure(Securit
yPortDescriptor.java:171)
06/04/07 14:59:32 at oracle.j2ee.ws.server.mgmt.runtime.mbean.ServerInterceptorPortRuntime.rec
onfigure(ServerInterceptorPortRuntime.java:108)
06/04/07 14:59:32 at oracle.j2ee.ws.server.mgmt.runtime.mbean.ServerInterceptorPortRuntime
|
未使用 OC4J Application Server Control 为运行中的服务正确填充密码
或者密钥存储器具有 SKI (Subject Key Identifier),10.1.3 中的错误 (4996924) 意味着,使用 BST (Binary Security Token) 验证密钥失败(如果使用 Windows 平台)。
|
重复这些步骤,在 Oracle Application Server Control 中编辑 Web 服务安全设置。确保将密码添加到适当位置
确保密钥存储器具有 SKI (X509 V3)。使用通过 keytool.exe 生成的密钥存储器不会奏效,因为它创建的是 X509 V1 — 不具有 SKI。
|
javax.xml.rpc.soap.SOAPFaultException:User [albert] does not exist in system.
at oracle.j2ee.ws.client.StreamingSender._raiseFault(StreamingSender.java:553)
at oracle.j2ee.ws.client.StreamingSender._sendImpl(StreamingSender.java:390)
at oracle.j2ee.ws.client.StreamingSender._send(StreamingSender.java:111)
at client.runtime.MyWebService1SoapHttp_Stub.echoMe(MyWebService1SoapHttp_Stub.java:78)
at com.cmaxwell.secure.MyWebService1SoapHttpPortClient.echoMe(MyWebService1SoapHttpPortClient.java:43)
at com.cmaxwell.secure.MyWebService1SoapHttpPortClient.main(MyWebService1SoapHttpPortClient.java:31)
|
服务器项目的 jazn-data.xml 没有使用 albertuser 填充。 |
重复该步骤,在 OC4J application Server Control 中添加新的应用程序用户“albert”。 |
oracle.j2ee.ws.common.soap.fault.SOAP11FaultException:java.lang.NullPointerException
at oracle.j2ee.ws.common.mgmt.runtime.InterceptorChainImpl.createSoapFaultException(InterceptorChainImpl.java:329)
|
客户端部署描述符 (MyWebService1SoapHttp_stub.xml) 具有以下问题
<verify-timestamp created="false" expiry="28800"/>
<add-timestamp created="false" expiry="28800"/>
这在服务器和客户端上必须匹配。由于某种原因,created="false" 会产生问题。
|
在服务器和客户端配置文件中包含
<verify-timestamp created="true" expiry="28800"/>
<add-timestamp created="true" expiry="28800"/>
或者从这两个配置文件中完全移除该行。
|
WARNING:Unable to connect to URL:http://localhost:8888/Application1-service-context-root/MyWebService1SoapHttpPort due to java.security.PrivilegedActionException:javax.xml.soap.SOAPException:Message send failed:Connection refused:connect
java.rmi.RemoteException:; nested exception is:
HTTP transport error:javax.xml.soap.SOAPException:java.security.PrivilegedActionException:javax.xml.soap.SOAPException:Message send failed:Connection refused:connect
|
服务无法访问服务器。
或
在关闭 JDeveloper 之前未停止 HTTP Analzer。这意味着,Analyzer 端口号 8099 在 Web Browser 和 Proxy 设置中仍然有效。始终在关闭 JDeveloper 之前关闭 Analyzer。
|
查看是否正确设置了 HTTP Proxy Server。如果您在本机工作,请通过 Tools -> Web Browser and Proxy 关闭它(删除 Port 和所有异常) |
获得更多信息
Oracle 技术网
JDeveloper 10g
Oracle Web Services Manager
面向服务的体系结构中心
Oracle 安全性技术中心
|