2006年 6月 14日 水曜日 Accessing JAX-WS 2.0 with SSL in Glassfish
作業ディレクトリは、図1になります。
図 1.
1.サーバー側
package endpoint;
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.annotation.Resource;
import javax.xml.ws.WebServiceContext;
@WebService(
name="MyHelloWorld",
serviceName="MyHelloWorldService",
targetNamespace="http://javaee5.com/jaxws/helloworld"
)
public class HelloWorld{
//the implementation class must have a default public constructor
public HelloWorld() {};
//
@Resource WebServiceContext wsContext;
@WebMethod(operationName="mySayHello", action="urn:mySayHello")
public String sayHello(String name){
return name + "'s user principal is "
+ wsContext.getUserPrincipal();
}
}
JAX-WS 2.0からJSR 181のannotationを使って、直接にサービスクラスを実装するだけで、開発はとてもシンプルとなってます。 List 1.をコンパイルして、 Glassfishから提供されているユーティリティwsgenを用いて、対応したWSDLファイルを生成できます。
~/ssl> javac -classpath %GLASSFISH_HOME%/lib/javaee.jar -d ./build/classes/service -g endpoint/HelloWorld.java
~/ssl> wsgen.bat -cp ./build/classes/service -keep -d ./build/classes/service -r ./build/generated -wsdl endpoint.HelloWorld
warファイルをパッケージするには、List 2.のweb.xmlを使います。相互認証を行うため、<auth-method>ではCLIENT-CERTと設定します。サービスクラスはWebServiceContext.getUserPrincipal()を読んでるため、その設定はList 3.のsun-web.xmlの<security-role-mapping>で行います。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:j2ee="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.5"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<description>WebTier for the HelloWorld Service</description>
<display-name>HelloWorldWAR</display-name> <servlet>
<description>Endpoint for HelloWorld Web Service</description>
<display-name>HelloWorldWebService</display-name>
<servlet-name>MyHelloWorld</servlet-name>
<servlet-class>endpoint.HelloWorld</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet> <servlet-mapping>
<servlet-name>MyHelloWorld</servlet-name>
<url-pattern>/HelloWorldService</url-pattern>
</servlet-mapping> <security-constraint>
<web-resource-collection>
<web-resource-name>Secure Area</web-resource-name>
<url-pattern>/HelloWorldService</url-pattern>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>ENGINEER</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<login-config>
<auth-method>CLIENT-CERT</auth-method>
<realm-name>certificate</realm-name>
</login-config>
<security-role>
<role-name>ENGINEER</role-name>
</security-role>
</web-app>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sun-web-app
PUBLIC "-//Sun Microsystems,
Inc.//DTD Application Server 9.0 Servlet 2.5//EN"
"http://www.sun.com/software/appserver/dtds/sun-web-app_2_5-0.dtd">
<sun-web-app>
<context-root>/HelloWorldService</context-root>
<security-role-mapping>
<role-name>ENGINEER</role-name>
<principal-name>
CN=zerra, OU=JPE, O=Sun, L=HaiDian, S=Beijing, C=China
</principal-name>
</security-role-mapping>
</sun-web-app>
asadminコマンドツールを使ってデプロイします。
~/ssl/archive> jar cvf helloworld-webservice.war WEB-INF/
~/ssl/archive> asadmin.bat deploy --user admin --passwordfile s1as_password.txt --host localhost --port 4848 --contextroot helloworld-webservice --upload=true --target server helloworld-webservice.war
2.クライアント側
サーバーで公開されているサービス(WSDL)から、Glassfishのユーティリティwsimportを使い、アクセスするためのクラスを生成します。
~/ssl> wsimport.bat -keep -d ./build/classes/client https://zerra:8181/helloworld-webservice/HelloWorldService?WSDL
生成されたクラスをimportして、クライアントのクラス(List 4.)を作ります。WebServiceRefのwsdlLocationでhttpsの指定にご注目。そしてクラスパスを指定し、クラスをコンパイルします。
package client;
import javax.xml.ws.WebServiceRef;
import com.javaee5.jaxws.helloworld.MyHelloWorldService;
import com.javaee5.jaxws.helloworld.MyHelloWorld;
public class WSClient{
@WebServiceRef(wsdlLocation=
"https://zerra:8181/helloworld-webservice/HelloWorldService?WSDL")
static MyHelloWorldService service;
public static void main(String[] args){
try{
WSClient client = new WSClient();
client.callEndpoint(args[0]);
}catch(Exception e){
e.printStackTrace();
}
}
public void callEndpoint(String name){
try{
MyHelloWorld port = service.getMyHelloWorldPort();
System.out.println(port.mySayHello(name));
}catch(Exception e){
e.printStackTrace();
}
}
}
~/ssl> javac -d ./build/classes/client -classpath %GLASSFISH_HOME%/lib/javaee.jar\;$GLASSFISH_HOME/lib/appserv-ws.jar\;./build/classes/client client/WSClient.java
サーバーと相互認証を行うには、クライアントが自分のキーを生成する必要があり、それをサーバーにあるトラストストーアに導入します。具体的な手順はImport Client's cert into Glassfishに書いてあります。
準備が整ったら、サーバーのトラストストーアとクライアントのキーストーアをVMARGSという環境変数に設定し、実行します。
~/ssl/build/classes/client> set VMARGS=-Djavax.net.ssl.trustStore=%GLASSFISH_HOME%/domains/domain1/config/cacerts.jks -Djavax.net.ssl.trustStorePassword=changeit -Djavax.net.ssl.keyStore=E:\ssl\clientCertificate\xiaojunkeystore.jks -Djavax.net.ssl.keyStorePassword=changeit
~/ssl/build/classes/client> appclient.bat client.WSClient Duke
Duke's user principal is CN=zerra, OU=JPE, O=Sun, L=HaiDian, S=Beijing, C=China
Posted by xiaojun ( 6月 14日 2006年, 04:26:02 午後 JST ) Permalink 投稿されたコメント [0]
Import Client's cert into Glassfish
Glassfishと双方向認証を行うには、クライアントが自分のkeyを生成し、それをGlassfishサーバーサイドにあるトラストストーアに導入する必要があります。 以下その手順を示します。
1.クライアント側のkeyの生成
JDK 5.0で提供されているkeytoolを使い、簡単にkeyを生成できます。
keytool -genkey -validity 10000 -alias clientkey -dname "CN=zerra, OU=JPE, O=Sun, L=HaiDian, S=Beijing, C=China" -keypass changeit -storepass changeit
2.クライアントの証明書の導出
keytool -export -alias clientkey -storepass changeit -file client.cer -keystore clientstore.jks
このコマンドにより、キー情報が中間ファイルclient.cerに保存されます。
3.クライアントの証明書の導入
keytool -import -noprompt -v -trustcacerts -alias clientkey -file client.cer -keystore ${GLASSFISH_HOME}/domains/domain1/config/cacerts.jks -storepass changeit
${GLASSFISH_HOME}が実際のインストールパスをあらわします。これで、クライアントの証明書がサーバーにあるトラストストーアに保存されました。
下のコマンドを発行し、clientkeyをgrepして確認できます。
keytool -list -v -keystore cacerts.jks -storepass changeit
別名: clientkey
作成日: 2006/06/05
エントリのタイプ: trustedCertEntry
所有者: CN=zerra, OU=JPE, O=Sun, L=HaiDian, ST=Beijing, C=China
実行者: CN=zerra, OU=JPE, O=Sun, L=HaiDian, ST=Beijing, C=China
シリアル番号: 4483a90a
有効日: Mon Jun 05 12:46:18 JST 2006 有効期限: Fri Oct 21 12:46:18 JST 2033
証明書のフィンガープリント:
MD5: 2B:A2:0C:5C:0D:D6:4C:00:09:A3:84:B0:A6:60:53:4D
SHA1: A4:CE:41:4E:12:F3:EB:29:5A:8A:A0:76:87:08:C8:0D:C5:1D:A7:E3
また、証明書をトラストストーアから削除するには、下のコマンドで消せます。
keytool -delete -alias clientkey -keystore ${GLASSFISH_HOME}/domains/domain1/config/cacerts.jks -storepass changeit
Posted by xiaojun ( 6月 07日 2006年, 11:01:34 午前 JST ) Permalink 投稿されたコメント [0]