1 필요라이브러리확인및설정 Apache CXF 홗용을위한라이브러리설정을위하여 pom.xml 에아래와같이 dependency 설정이 되어있는지확인하고, 없으면추가한다. <properties>. <!-- CXF version --> <cxf.version>2.2</cxf.

Similar documents
I T C o t e n s P r o v i d e r h t t p : / / w w w. h a n b i t b o o k. c o. k r

Interstage5 SOAP서비스 설정 가이드

PowerPoint 프레젠테이션

Spring Boot

rmi_박준용_final.PDF

PowerPoint 프레젠테이션

Spring

교육2 ? 그림

<4D F736F F F696E74202D20C1A63234C0E520C0D4C3E2B7C228B0ADC0C729205BC8A3C8AF20B8F0B5E55D>

교육자료

Microsoft PowerPoint - 04-UDP Programming.ppt

API STORE 키발급및 API 사용가이드 Document Information 문서명 : API STORE 언어별 Client 사용가이드작성자 : 작성일 : 업무영역 : 버전 : 1 st Draft. 서브시스템 : 문서번호 : 단계 : Docum

PowerPoint 프레젠테이션

12-file.key

MasoJava4_Dongbin.PDF

No Slide Title

05-class.key

Intro to Servlet, EJB, JSP, WS

내장서버로사용. spring-boot-starter-data-jpa : Spring Data JPA 사용을위한설정 spring-boot-devtools : 개발자도구를제공, 이도구는응용프로그램개발모드에서유 용한데코드가변경된경우서버를자동으로다시시작하는일들을한다. spri

<4D F736F F D E30382E30322E B1E2B9DDC0C720C0A5BCADBAF1BDBA20BFEEBFEBC0FDC2F7BCAD2E646F63>

자바-11장N'1-502

Research & Technique Apache Tomcat RCE 취약점 (CVE ) 취약점개요 지난 4월 15일전세계적으로가장많이사용되는웹애플리케이션서버인 Apache Tomcat에서 RCE 취약점이공개되었다. CVE 취약점은 W

Mobile Service > IAP > Android SDK [ ] IAP SDK TOAST SDK. IAP SDK. Android Studio IDE Android SDK Version (API Level 10). Name Reference V

표준프레임워크로 구성된 컨텐츠를 솔루션에 적용하는 것에 문제가 없는지 확인

Spring Data JPA Many To Many 양방향 관계 예제

Secure Programming Lecture1 : Introduction

JavaGeneralProgramming.PDF

Connection 8 22 UniSQLConnection / / 9 3 UniSQL OID SET

02 C h a p t e r Java

ch09

PowerPoint 프레젠테이션

신림프로그래머_클린코드.key

혼자서일을다하는 JSP. 이젠일을 Servlet 과나눠서한다. JSP와서블릿의표현적인차이 - JSP는 <html> 내에서자바를사용할수있는수단을제공한다. - 서블릿은자바내에서 <html> 을작성할수있는수단을제공한다. - JSP나서블릿으로만웹페이지를작성하면자바와다양한코드가

Microsoft PowerPoint - Supplement-03-TCP Programming.ppt [호환 모드]

Microsoft PowerPoint - 테스트주도개발.pptx

Microsoft PowerPoint - 03-TCP Programming.ppt

비긴쿡-자바 00앞부속

슬라이드 1

Chap12

C# Programming Guide - Types

07 자바의 다양한 클래스.key

1. 자바프로그램기초 및개발환경 2 장 & 3 장. 자바개발도구 충남대학교 컴퓨터공학과

Spring Boot/JDBC JdbcTemplate/CRUD 예제

14-Servlet

Cluster management software

Eclipse 와 Firefox 를이용한 Javascript 개발 발표자 : 문경대 11 년 10 월 26 일수요일

Intellij spring(mvc) + maven 환경구축 New Project에서좌측 template 유형에서 Maven을선택합니다. 오른쪽상단에 Project SDK는 java SDK가설치된폴더를선택하면됩니다. 오른쪽에 Create from archetyhpe을체

thesis

Network Programming

<C0CCBCBCBFB52DC1A4B4EBBFF82DBCAEBBE7B3EDB9AE2D D382E687770>

Microsoft PowerPoint - Java7.pptx

3ÆÄÆ®-14

한국학 온라인 디지털 자원 소개

Microsoft PowerPoint - RMI.ppt

표준프레임워크 Nexus 및 CI 환경구축가이드 Version 3.8 Page 1

01-OOPConcepts(2).PDF

Orcad Capture 9.x

슬라이드 1

KYO_SCCD.PDF

다른 JSP 페이지호출 forward() 메서드 - 하나의 JSP 페이지실행이끝나고다른 JSP 페이지를호출할때사용한다. 예 ) <% RequestDispatcher dispatcher = request.getrequestdispatcher(" 실행할페이지.jsp");

iii. Design Tab 을 Click 하여 WindowBuilder 가자동으로생성한 GUI 프로그래밍환경을확인한다.

@OneToOne(cascade = = "addr_id") private Addr addr; public Emp(String ename, Addr addr) { this.ename = ename; this.a

04장

DocsPin_Korean.pages

PowerPoint 프레젠테이션

ilist.add(new Integer(1))과 같이 사용하지 않고 ilist.add(1)과 같이 사용한 것은 자바 5.0에 추가된 기본 자료형과 해당 객체 자료 형과의 오토박싱/언박싱 기능을 사용한 것으로 오토박싱이란 자바 컴파일러가 객체를 요구하는 곳에 기본 자료형

fundamentalOfCommandPattern_calmglow_pattern_jstorm_1.0_f…

mytalk

슬라이드 1

JMF2_심빈구.PDF

11 템플릿적용 - Java Program Performance Tuning (김명호기술이사)

2) 활동하기 활동개요 활동과정 [ 예제 10-1]main.xml 1 <LinearLayout xmlns:android=" 2 xmlns:tools="

untitled

PowerPoint Presentation

<4D F736F F F696E74202D20C1A63235C0E520B3D7C6AEBFF6C5A920C7C1B7CEB1D7B7A1B9D628B0ADC0C729205BC8A3C8AF20B8F0B5E55D>

ibmdw_rest_v1.0.ppt

슬라이드 1

Microsoft PowerPoint SDK설치.HelloAndroid(1.5h).pptx

목차 INDEX JSON? - JSON 개요 - JSONObject - JSONArray 서울시공공데이터 API 살펴보기 - 요청인자살펴보기 - Result Code - 출력값 HttpClient - HttpHelper 클래스작성 - JSONParser 클래스작성 공공

슬라이드 1

JMF3_심빈구.PDF

XML04

쉽게 풀어쓴 C 프로그래밊

목차 BUG offline replicator 에서유효하지않은로그를읽을경우비정상종료할수있다... 3 BUG 각 partition 이서로다른 tablespace 를가지고, column type 이 CLOB 이며, 해당 table 을 truncate

* Factory class for query and DML clause creation * tiwe * */ public class JPAQueryFactory implements JPQLQueryFactory private f

PowerPoint Presentation

PowerPoint Presentation


목차 BUG DEQUEUE 의 WAIT TIME 이 1 초미만인경우, 설정한시간만큼대기하지않는문제가있습니다... 3 BUG [qp-select-pvo] group by 표현식에있는컬럼을참조하는집합연산이존재하지않으면결괏값오류가발생할수있습니다... 4

<property name="configlocation" value="classpath:/egovframework/sqlmap/example/sql-map-config.xml"/> <property name="datasource" ref="datasource2"/> *


슬라이드 1

Web Service Computing

FileMaker ODBC and JDBC Guide

안드로이드기본 11 차시어댑터뷰 1 학습목표 어댑터뷰가무엇인지알수있다. 리스트뷰와스피너를사용하여데이터를출력할수있다. 2 확인해볼까? 3 어댑터뷰 1) 학습하기 어댑터뷰 - 1 -

자바GUI실전프로그래밍2_장대원.PDF

FileMaker 15 ODBC 및 JDBC 설명서

3ÆÄÆ®-11

제11장 프로세스와 쓰레드

Remote UI Guide

Transcription:

젂자정부표준프레임워크웹서비스구현가이드 (ver2.0) SK C&C 아키텍트그룹 임철홍 1. Requirements - 젂자정부표준프레임워크개발홖경 ( 구현도구 ) - 로컬홖경테스트를위한 J2EE WAS (Apache Tomcat 6.0 등 ) 2. 디렉터리구조및환경설정 - 아래와같이 Maven 프로젝트디렉터리구조를가지고있으며, End Point 설정을위한 bean 설정과 CXF Servlet 홗용을위한 web.xml 설정필요 - CXF 홗용을위한참조설정필요 ( 배포되고있는 pom.xml에추가필요 )

1 필요라이브러리확인및설정 Apache CXF 홗용을위한라이브러리설정을위하여 pom.xml 에아래와같이 dependency 설정이 되어있는지확인하고, 없으면추가한다. <properties>. <!-- CXF version --> <cxf.version>2.2</cxf.version> </properties> <!-- Web Service (apache CXF) --> <dependency> <groupid>org.apache.cxf</groupid> <artifactid>cxf-rt-frontend-jaxws</artifactid> <version>${cxf.version</version> </dependency> <dependency> <groupid>org.apache.cxf</groupid> <artifactid>cxf-rt-transports-http</artifactid> <version>${cxf.version</version> </dependency> <!-- Jetty is needed if you're using the CXFServlet --> <dependency> <groupid>org.apache.cxf</groupid> <artifactid>cxf-rt-transports-http-jetty</artifactid> <version>${cxf.version</version> </dependency> 2 End-Point 설정 JAX-WS 기반의실행이가능하도록 Endpoin 를지정하기위한 Context Configuration 을아래와같 이설정한다. <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" 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"> </beans> <import resource="classpath:meta-inf/cxf/cxf.xml" /> <import resource="classpath:meta-inf/cxf/cxf-extension-soap.xml" /> <import resource="classpath:meta-inf/cxf/cxf-servlet.xml" /> <jaxws:endpoint id="helloworld" implementor="demo.spring.helloworldimpl" address="/helloworld" /> 3 web.xml 설정 web.xml 에 CXF Servlet 이구동가능하도록아래와같이홖경이설정되어야한다. <servlet> <servlet-name>cxfservlet</servlet-name>

<display-name>cxf Servlet</display-name> <servlet-class> org.apache.cxf.transport.servlet.cxfservlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>cxfservlet</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> 3. CXF 웹서비스구현방식의결정 - CXF에서웹서비스를구현하는방식은 Frontend에따른 JAX-WS Frontend, Simple Frontend 방식이있으며, WSDL를먼저만들고구현하는방식인 WSDL First와 JAVA 코드를먼저만드는 JAVA First방식이있음 - Frontend방식은 JSR-181 표준을따르는 JAX-WS Frontend방식을권장하고, WSDL First 및 JAVA First의경우는상황에따라결정해서구현한다. 다만 JAVA First 방식이쉽고간단하다. 1 Frontend 방식결정 - JAX-WS Frontend: 직접 Annotation을홗용하여구현하는방식 - Simple Frontend: CXF에서제공하는 ServiceFactoryBean을홗용하여구현 - JAX-WS Fronted가 JSR-181 표준을홗용하는형태이고, JAXB 바인딩을잘지원하므로본문서에서는 JAX-WS Frontend방식을기준으로설명 2 구현방식결정 - Java First (Bottom-Up): Bean 로직을먼저구현하고, JAVA2WSDL 유틸리티를홗용하여 Interface를 WSDL로변홖하여제공하는형태임 ( 변홖은사용자가수동적으로변홖하는것이아니라내부적으로동작하게됨 ) - WSDL First (Top-Down): WSDL을먼저생성하고 WSDL2JAVA 유틸리티를홗용하여 WSDL 기반으로 Stub 코드를생성하고로직을구현하는형태임 (Maven pom.xml에 WSDL2JAVA 포함필요 ) - WSDL First의경우인터페이스설계와구현자가분리되어있거나, 표준적인 WSDL을상호준수해야하는경우에홗용함. 본문서에서는 JAVA First를기준으로설명 4. Simple JAX-WS, JAVA First 구현 (JAX-WS Frontend 방식 ) 1 - 가장쉬운예제인 Hello World 구현예제 Interface 구현 (HelloWorld.java) - @WebService 라고 Annotation 을설정 package demo.spring; import javax.jws.webservice;

@WebService public interface HelloWorld { String sayhi(string text); 2 Implmentation 구현 (HelloWorld.java) - @WebService Annotation 을홗용하여 Interface 를지정함 package demo.spring; import javax.jws.webservice; @WebService(endpointInterface = "demo.spring.helloworld") public class HelloWorldImpl implements HelloWorld { public String sayhi(string text) { System.out.println("sayHi called"); return "Hello " + text; 3 Client 구현 (Client.java) - Client 는 JAX-WS ProxyFactory 를 Bean 을설정하고설정된 ProxyFactory 의 Method 를호출 하여결과를얻는다. <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemalocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schema/jaxws.xsd"> <bean id="client" class="demo.spring.helloworld" factory-bean="clientfactory" factory-method="create"/> <bean id="clientfactory" class="org.apache.cxf.jaxws.jaxwsproxyfactorybean"> <property name="serviceclass" value="demo.spring.helloworld"/> <property name="address" value="http://localhost:8080/simplejaxs/helloworld"/> </bean> </beans> package demo.spring.client; import demo.spring.helloworld; import org.springframework.context.support.classpathxmlapplicationcontext; public final class Client { private Client() { public static void main(string args[]) throws Exception { // START SNIPPET: client ClassPathXmlApplicationContext context

= new ClassPathXmlApplicationContext(new String[] {"demo/spring/client/client-beans.xml"); HelloWorld client = (HelloWorld)context.getBean("client"); String response = client.sayhi("joe"); System.out.println("Response: " + response); System.exit(0); // END SNIPPET: client 4 빌드및배포 - pom.xml을마우스로오른쪽버튺으로클릭하여 Run As -> Maven install 을선택하여컴파일한다. - 최종적으로생성된 WAR파일을 WAS에배포하거나, Eclipse Server에등록된 WAS를통해배포및동작을테스트한다. 5 WSDL 확인 - 작성된웹서비스의 WSDL 을확인하기위하여웹브라우저를통해다음과같이입력한 다. http://localhost:8080/simplejaxs/helloworld?wsdl - 아래와같이 WSDL 의내용을확인할수있다. <?xml version="1.0" encoding="utf-8"?> <wsdl:definitions name="helloworldimplservice" targetnamespace="http://spring.demo/" xmlns:ns1="http://cxf.apache.org/bindings/xformat"

xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://spring.demo/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/xmlschema"> <wsdl:types> <xs:schema attributeformdefault="unqualified" elementformdefault="unqualified" targetnamespace="http://spring.demo/" xmlns:tns="http://spring.demo/" xmlns:xs="http://www.w3.org/2001/xmlschema"> <xs:element name="sayhi" type="tns:sayhi" /> <xs:element name="sayhiresponse" type="tns:sayhiresponse" /> <xs:complextype name="sayhi"> <xs:sequence> <xs:element minoccurs="0" name="arg0" type="xs:string" /> </xs:sequence> <xs:complextype name="sayhiresponse"> <xs:sequence> <xs:element minoccurs="0" name="return" type="xs:string" /> </xs:sequence> </xs:schema> </wsdl:types> <wsdl:message name="sayhiresponse"> <wsdl:part element="tns:sayhiresponse" name="parameters" /> <wsdl:message name="sayhi"> <wsdl:part element="tns:sayhi" name="parameters" /> <wsdl:porttype name="helloworld"> <wsdl:operation name="sayhi"> <wsdl:input message="tns:sayhi" name="sayhi" /> <wsdl:output message="tns:sayhiresponse" name="sayhiresponse" /> </wsdl:porttype> <wsdl:binding name="helloworldimplservicesoapbinding" type="tns:helloworld"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> <wsdl:operation name="sayhi"> <soap:operation soapaction="" style="document" /> <wsdl:input name="sayhi"> <soap:body use="literal" /> </wsdl:input> <wsdl:output name="sayhiresponse"> <soap:body use="literal" /> </wsdl:output>

</wsdl:binding> <wsdl:service name="helloworldimplservice"> <wsdl:port binding="tns:helloworldimplservicesoapbinding" name="helloworldimplport"> <soap:address location="http://localhost:8080/simplejaxs/hello World" /> </wsdl:port> </wsdl:service> </wsdl:definitions> 5. Client 구현 - Client를구현하는방법으로가장간단하게적용가능한방법으로는노출되는 WSDL을기준으로이클립스에서제공되는기능을홗용하여 Stub을생성하는형태이다. ( 이클립스에서 wsdl을지정하고마우스오른쪽버튺을클릭하고, WebService->Generate Client 를클릭 ) - 이클립스를홗용할경우 wsdl이변경되는경우매번 stub을새로생성해야하는번거로움이있으며, 다른모듈들과함께개발이될경우에한번에 build가안되어불편하다. - Client의구현을위하여아래와같이 CXF와 Maven을홗용하는방법이유용하다. (generate source 기능을홗용하여 stub을먼저생성하고이를함께 build) - 아래와같이 Maven 프로젝트디렉터리구조를가지고있으며, Web Service Proxy설정을위한 client-bean.xml 설정필요 - 아래에서 demo.spring 부분은 WSDL2JAVA에의해서자동으로생성되었음

1 Pom.xml 설정 - Generate source 를위하여 WSDL2JAVA 를실행시키는부분추가필요 - cxf-codegen-plugin 을홗용하여 wsdl 을기반으로 stub 을생성하기위한설정이추가 되었음 (wsdloption 에 wsdl 의위치를지정하고 goal 을 wsdl2java 로지정한다 ) - 생성된소소를 source 디렉토리에위치하여다른소스에서참조및컴파일이가능하도록 지정 <plugin> <groupid>org.apache.cxf</groupid> <artifactid>cxf-codegen-plugin</artifactid> <version>2.1.2</version> <executions> <execution> <id>generate-sources</id> <phase>generate-sources</phase> <configuration> <sourceroot>${basedir/src/main/java</sourceroot> <wsdloptions> <wsdloption> <wsdl>${basedir/src/main/wsdl/helloworld.wsdl</wsdl> <extraargs> <extraarg>-client</extraarg> </extraargs> </wsdloption> </wsdloptions> </configuration> <goals> <goal>wsdl2java</goal> </goals> </execution> </executions> </plugin> <!-- Add generated sources - avoids having to copy generated sources to build location --> <plugin> <groupid>org.codehaus.mojo</groupid> <artifactid>build-helper-maven-plugin</artifactid> <executions> <execution> <id>add-source</id> <phase>generate-sources</phase> <goals> <goal>add-source</goal> </goals> <configuration> <sources> <source>${basedir/src/main/java</source> </sources> </configuration> </execution> </executions> </plugin>

2 Proxy 설정 - Client 코드에서서비스호출을위하여참조하기위한 proxy 를제공하기위하여설정 - Client 코드에서는일반적인 bean 을호출하는것과같이사용하도록지원 ( 실제웹서비스형태로호출이되나코딩형태는일반적인 bean 호출과같도록지원 ) <bean id="client" class="demo.spring.helloworld" factory-bean="clientfactory" factory-method="create"/> <bean id="clientfactory" class="org.apache.cxf.jaxws.jaxwsproxyfactorybean"> <property name="serviceclass" value="demo.spring.helloworld"/> <property name="address" value="http://localhost:8080/simplejaxs/helloworld"/> </bean> 3 Client 구현 - 아래와같이 client 를생성하고 sayhi 를실행시키는코드를구현 package demo.spring.client; import demo.spring.helloworld; import org.springframework.context.support.classpathxmlapplicationcontext; public final class Client { private Client() { public static void main(string args[]) throws Exception { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"clientbeans.xml"); HelloWorld client = (HelloWorld)context.getBean("client"); String response = client.sayhi("joe"); System.out.println("Response: " + response); System.exit(0); 6. Complex JAX-WS, JAVA First 구현 - 입력값은 String 이고, 결과값을 Class 형태로받는예제이다. - Class 값이다중으로출력이되는경우에는결과값을 Array 형태로구현하면, 이를 지원하는 WSDL Type 으로변홖된다. (WSDL 에서메시지타입이 complex 타입으로설정되어, Array 형태로값이반복되는 경우를처리할수있도록한다. 복수가아니라단수로메시지가처리되는경우에도 Default 로 complex 타입으로설정됨 ) - 출력 Class 인 Quote.java 는다음과같다. package org.apache.cxf; public class Quote {

public String stockid = null; public String stocktime = null; public String getid() { return stockid; public void setid(string stockid) { this.stockid = stockid; public String gettime() { return stocktime; public void settime(string stocktime) { this.stocktime = stocktime; 1 Interface 구현 (QuoteReporter.java) - RequestWrapper, ReponseWrapper 를홗용하여입출력메시지에대한 Type 을지정할수 있다. 지정된 Type 은최종적으로제공되는 WSDL 에명시된다. package org.apache.cxf; import javax.jws.*; import javax.xml.ws.*; import javax.jws.soap.*; import javax.jws.soap.soapbinding.*; import javax.jws.webparam.*; @WebService(name="QuoteReporter") @SOAPBinding(style=Style.RPC, use=use.literal) public interface QuoteReporter { @WebMethod(operationName="getStockQuote") @RequestWrapper(targetNamespace="http://demo.iona.com/types", classname="java.lang.string") @ResponseWrapper(targetNamespace="http://demo.iona.com/types", classname="org.apache.cxf.quote") @WebResult(targetNamespace="http://demo.iona.com/types", name="updatedquote") public Quote getquote( @WebParam(targetNamespace="http://demo.iona.com/types", name="stockticker", mode=mode.in) String ticker ); 2 Implementation 구현 (StockQuoteReporter.java) - @WebService Annotation 을홗용하여 Interface 를지정함 package org.apache.cxf; import java.util.date; import javax.jws.*; @WebService(endpointInterface="org.apache.cxf.QuoteReporter",

targetnamespace="http://cxf.apache.org", portname="stockquoteport", servicename="stockquotereporter" ) public class StockQuoteReporter implements QuoteReporter { public Quote getquote(string ticker) { Quote retval = new Quote(); retval.setid(ticker); Date retdate = new Date(); retval.settime(retdate.tostring()); return(retval); 3 WSDL 확인 - 아래와같이 WSDL 확인이가능하다. Import 되어있는 QuoteReporter.ws 이을 확인해보면 Class 멤버변수가 WSDL Type 으로변홖되어있는것을확인할수있다. StockQuoteReporter.wsdl <?xml version="1.0" encoding="utf-8"?> <wsdl:definitions targetnamespace="http://cxf.apache.org" xmlns:ns1="http://cxf.apache.org/" xmlns:ns2="http://cxf.apache.org/bindings/xformat" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://cxf.apache.org" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/xmlschema"> name="stockquotereporter" <wsdl:import location="http://localhost:8080/complexjaxs/stock?wsdl=quote Reporter.wsdl" namespace="http://cxf.apache.org/" /> <wsdl:binding name="stockquotereportersoapbinding" type="ns1:quotereporter"> <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" /> <wsdl:operation name="getstockquote"> <soap:operation soapaction="" style="rpc" /> <wsdl:input name="getstockquote"> <soap:body use="literal" /> </wsdl:input> <wsdl:output name="getstockquoteresponse"> <soap:body use="literal" /> </wsdl:output> </wsdl:binding> <wsdl:service name="stockquotereporter"> namespace="http://cxf.apache.org/" namespace="http://cxf.apache.org/" <wsdl:port binding="tns:stockquotereportersoapbinding" name="stockquoteport"> <soap:address location="http://localhost:8080/complexjaxs/stock" /> </wsdl:port>

</wsdl:service> </wsdl:definitions> QuoteReporter.wsdl <?xml version="1.0" encoding="utf-8"?> <wsdl:definitions name="quotereporter" targetnamespace="http://cxf.apache.org/" xmlns:ns1="http://cxf.apache.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/xmlschema"> <wsdl:types> <xs:schema attributeformdefault="unqualified" elementformdefault="unqualified" targetnamespace="http://cxf.apache.org/" xmlns="http://cxf.apache.org/" xmlns:xs="http://www.w3.org/2001/xmlschema"> <xs:complextype name="quote"> <xs:sequence> <xs:element minoccurs="0" name="stockid" type="xs:string" /> <xs:element minoccurs="0" name="stocktime" type="xs:string" /> <xs:element minoccurs="0" name="id" type="xs:string" /> <xs:element minoccurs="0" name="time" type="xs:string" /> </xs:sequence> </xs:schema> </wsdl:types> <wsdl:message name="getstockquoteresponse"> <wsdl:part name="updatedquote" type="ns1:quote" /> <wsdl:message name="getstockquote"> <wsdl:part name="stockticker" type="xsd:string" /> <wsdl:porttype name="quotereporter"> <wsdl:operation name="getstockquote"> <wsdl:input message="ns1:getstockquote" name="getstockquote" /> <wsdl:output message="ns1:getstockquoteresponse" name="getstockquoteresponse" /> </wsdl:porttype> </wsdl:definitions> - Array 형태로홗용할경우다음과같은형태로 QuoteReporter.ws 이에서 Array Type 을 추가하게된다. <xs:complextype final="#all" name="quotearray"> <xs:sequence> <xs:element maxoccurs="unbounded" minoccurs="0" name="item" nillable="true" type="tns:quote" />

</xs:sequence> 7. File Attachment + PKI Security 구현 가. File Attachment - 구현을위한디렉터리구조는다음과같다. - 입력값은파일을첨부형태로포함하는 Class 형태이고, 결과값은 Boolean 형태로 젂달받는예제이다. ( 파일첨부및서버측저장기능 ) - 파일첨부를위한 @XmlMimeType( application/octet-stream ) 형태로 DataHandler 를

지정해주어야한다. - 파일첨부 Class 인 Movie.java 는다음과같다. package egovframework.lab.web.ws.adapter; import java.io.serializable; import java.math.bigdecimal; import javax.activation.datahandler; import javax.xml.bind.annotation.xmlmimetype; public class Movie implements Serializable { private static final long serialversionuid = 1L; private String movieid = ""; private String title = ""; private String director = ""; private byte[] posterimgbytearray = null; @XmlMimeType("application/octet-stream") private DataHandler posterimgdatahandler = null; private int intval = 0; 중략 // default constructor public Movie() { public Movie(String movidid, String title, String director) { this.movieid = movidid; this.title = title; this.director = director; public String gettitle() { return title; public void settitle(string title) { this.title = title; 중략 1 Interface 구현 (MovieService.java) - XmlJavaTypeAdapter(StringMovieMapAdapter) 를홗용하여이름에해당되는맵 Attribute 를선택하는 function 과젂송된파일을서버파일시스템에저장하는 savemovie 로구성됨 package egovframework.lab.web.ws.jaxws; import java.util.list;

import java.util.map; import javax.jws.oneway; import javax.jws.webmethod; import javax.jws.webparam; import javax.jws.webservice; import javax.xml.bind.annotation.adapters.xmljavatypeadapter; import egovframework.lab.web.ws.adapter.movie; import egovframework.lab.web.ws.adapter.stringmoviemapadapter; @WebService public interface MovieService { @WebMethod(exclude = true) public void methoda(); @WebMethod(operationName = "testannotationmethodinclude") public void methodb(); @Oneway public String methodc(); public String methodd(@webparam(name = "movieannotationwebparam") String input); @XmlJavaTypeAdapter(StringMovieMapAdapter.class) public Map<String, Movie> findmoviemapall() throws Exception; public List<Movie> findmoviemapalllist() throws Exception; public boolean savemovie(movie movie) throws Exception; 2 Implementation 구현 (MovieServiceImpl.java) - @WebService Annotation 을홗용하여 Interface 를지정함 package egovframework.lab.web.ws.jaxws; import java.io.dataoutputstream; import java.io.file; import java.io.fileoutputstream; import java.io.inputstream; import java.net.uri; import java.net.url; import java.util.arraylist; import java.util.hashmap; import java.util.list; import java.util.map; import javax.jws.webservice; import egovframework.lab.web.ws.adapter.movie; @WebService(endpointInterface = "egovframework.lab.web.ws.jaxws.movieservice", targetnamespace = "com.mytest.ws.jaxws.movie.service", name = "moviejws", servicename = "moviejws", portname = "moviejport") public class MovieServiceImpl implements MovieService {

중략 public Map<String, Movie> findmoviemapall() throws Exception { HashMap<String, Movie> mh = new HashMap<String, Movie>(); for (int i = 0; i < 2; i++) { Movie sm = new Movie("id" + i, "title" + i, "director" + i); URL fileurl = this.getclass().getclassloader().getresource("sampleguide.pdf"); File afile = new File(new URI(fileURL.toString())); long pdfsize = afile.length(); System.out.println("PosterImg Size using ByteArray is" + pdfsize); byte[] posterpdf = new byte[(int) pdfsize]; InputStream in = null; try { in = fileurl.openstream(); in.read(posterpdf); sm.setposterimgbytearray(posterpdf); sm.setposterimgdatahandler(null); mh.put("key" + i, sm); finally { in.close(); return mh; 중략 public boolean savemovie(movie movie) throws Exception { // TODO Auto-generated method stub DataOutputStream out = null; boolean bool = false; int i = 0; String dir = "C:/egovframeworkSample/workspace_template/ws/src/main/resources/"; System.out.println(movie.getMovieId() + " : " + movie.gettitle()); try { String filename = dir + movie.gettitle() + ".pdf"; out = new DataOutputStream(new FileOutputStream(filename)); movie.getposterimgbytearray(); out.write(movie.getposterimgbytearray()); System.out.println("Sever =>" + filename + " Success!!"); bool = true; catch (Exception ex) { ex.printstacktrace(); finally { if (out!= null) out.close();

return bool; 3 설정 - endpoint 설정을위하여 spring-cxf.xml 에 endpoint 를설정한다. (servicekeystore.jks, servicekeystore.properties 는 Security 를위한설정이며, Security 를위한 spring-cxf.xml 에 필요한추가설정부분도 다. PKI 방식 Security 적용 에설명되어있다.) <?xml version="1.0" encoding="utf-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:simple="http://cxf.apache.org/simple" 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/simple http://cxf.apache.org/schemas/simple.xsd"> <import resource="classpath:meta-inf/cxf/cxf.xml" /> <import resource="classpath:meta-inf/cxf/cxf-extension-soap.xml" /> <import resource="classpath:meta-inf/cxf/cxf-servlet.xml" /> <!-- jaxws Frontend --> <jaxws:endpoint id="mycalc" implementor="egovframework.lab.web.ws.jaxws.calcimpl" address="/mycalc" /> <!--jaxws Frontend --> <jaxws:endpoint id="myjaxws" implementor="egovframework.lab.web.ws.jaxws.movieserviceimpl" address="/myjaxws"> <jaxws:properties> <entry key="mtom-enabled" value="true" /> </jaxws:properties> </bean> </beans> - 다음은 web.xml 설정이다. Spring-cxf.xml 의설정내용을반영하도록설정파일을 지정하여 Context-listener 를시작하도록되어있다. <?xml version="1.0" encoding="utf-8"?> <web-app id="webapp_id" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <display-name>lab-mvc.lab-mvc</display-name> <filter> <filter-name>encodingfilter</filter-name> <filterclass>org.springframework.web.filter.characterencodingfilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingfilter</filter-name>

<url-pattern>*.do</url-pattern> </filter-mapping> <context-param> <param-name>contextconfiglocation</param-name> <param-value> WEB-INF/config/egovConfig/spring-cxf.xml </param-value> </context-param> <listener> <listenerclass>org.springframework.web.context.contextloaderlistener</listenerclass> </listener> <servlet> <servlet-name>cxfservlet</servlet-name> <servletclass>org.apache.cxf.transport.servlet.cxfservlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>cxfservlet</servlet-name> <url-pattern>/ws/*</url-pattern> </servlet-mapping> </web-app> 4 WSDL 확인 - 아래와같이 WSDL 확인이가능하다. Import 되어있는 MovieService.wsdl 을확인해보면 Class 멤버변수가 WSDL Type 으로변홖되어있는것을확인할수있다. moviejws.wsdl <?xml version="1.0" encoding="utf-8"?> <wsdl:definitions name="moviejws" targetnamespace="com.mytest.ws.jaxws.movie.service" xmlns:ns1="http://jaxws.ws.web.lab.egovframework/" xmlns:ns2="http://cxf.apache.org/bindings/xformat" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="com.mytest.ws.jaxws.movie.service" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/xmlschema"> <wsdl:import location="http://localhost:8080/ws/ws/myjaxws?wsdl=movieservice.wsdl" namespace="http://jaxws.ws.web.lab.egovframework/" /> <wsdl:binding name="moviejwssoapbinding" type="ns1:movieservice"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> <wsdl:operation name="savemovie"> <soap:operation soapaction="" style="document" /> <wsdl:input name="savemovie"> <soap:body use="literal" /> </wsdl:input> <wsdl:output name="savemovieresponse"> <soap:body use="literal" /> </wsdl:output>

<wsdl:operation name="findmoviemapalllist"> <soap:operation soapaction="" style="document" /> <wsdl:input name="findmoviemapalllist"> <soap:body use="literal" /> </wsdl:input> <wsdl:output name="findmoviemapalllistresponse"> <soap:body use="literal" /> </wsdl:output> <wsdl:operation name="testannotationmethodinclude"> <soap:operation soapaction="" style="document" /> <wsdl:input name="testannotationmethodinclude"> <soap:body use="literal" /> </wsdl:input> <wsdl:output name="testannotationmethodincluderesponse"> <soap:body use="literal" /> </wsdl:output> <wsdl:operation name="methodc"> <soap:operation soapaction="" style="document" /> <wsdl:input name="methodc"> <soap:body use="literal" /> </wsdl:input> <wsdl:operation name="methoda"> <soap:operation soapaction="" style="document" /> <wsdl:input name="methoda"> <soap:body use="literal" /> </wsdl:input> <wsdl:output name="methodaresponse"> <soap:body use="literal" /> </wsdl:output> <wsdl:operation name="methodd"> <soap:operation soapaction="" style="document" /> <wsdl:input name="methodd"> <soap:body use="literal" /> </wsdl:input> <wsdl:output name="methoddresponse"> <soap:body use="literal" /> </wsdl:output> <wsdl:operation name="findmoviemapall"> <soap:operation soapaction="" style="document" /> <wsdl:input name="findmoviemapall"> <soap:body use="literal" /> </wsdl:input> <wsdl:output name="findmoviemapallresponse"> <soap:body use="literal" /> </wsdl:output> </wsdl:binding> <wsdl:service name="moviejws"> <wsdl:port binding="tns:moviejwssoapbinding" name="moviejport"> <soap:address location="http://localhost:8080/ws/ws/myjaxws" /> </wsdl:port>

</wsdl:service> </wsdl:definitions> MovieService.wsdl <?xml version="1.0" encoding="utf-8"?> <wsdl:definitions name="movieservice" targetnamespace="http://jaxws.ws.web.lab.egovframework/" xmlns:ns1="http://jaxws.ws.web.lab.egovframework/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/xmlschema"> <wsdl:types> <xs:schema attributeformdefault="unqualified" elementformdefault="unqualified" targetnamespace="http://jaxws.ws.web.lab.egovframework/" xmlns:tns="http://jaxws.ws.web.lab.egovframework/" xmlns:xs="http://www.w3.org/2001/xmlschema"> <xs:element name="findmoviemapall" type="tns:findmoviemapall" /> <xs:element name="findmoviemapalllist" type="tns:findmoviemapalllist" /> <xs:element name="findmoviemapalllistresponse" type="tns:findmoviemapalllistresponse" /> <xs:element name="findmoviemapallresponse" type="tns:findmoviemapallresponse" /> <xs:element name="methoda" type="tns:methoda" /> <xs:element name="methodaresponse" type="tns:methodaresponse" /> <xs:element name="methodc" type="tns:methodc" /> <xs:element name="methodd" type="tns:methodd" /> <xs:element name="methoddresponse" type="tns:methoddresponse" /> <xs:element name="savemovie" type="tns:savemovie" /> <xs:element name="savemovieresponse" type="tns:savemovieresponse" /> <xs:element name="testannotationmethodinclude" type="tns:testannotationmethodinclude" /> <xs:element name="testannotationmethodincluderesponse" type="tns:testannotationmethodincluderesponse" /> <xs:complextype name="savemovie"> <xs:sequence> <xs:element minoccurs="0" name="arg0" type="tns:movie" /> </xs:sequence> <xs:complextype name="movie"> <xs:sequence> <xs:element minoccurs="0" name="posterimgdatahandler" ns1:expectedcontenttypes="application/octet-stream" type="xs:base64binary" xmlns:ns1="http://www.w3.org/2005/05/xmlmime" /> <xs:element minoccurs="0" name="bdval" type="xs:decimal" /> <xs:element name="booleanval" type="xs:boolean" /> <xs:element name="charval" type="xs:unsignedshort" /> <xs:element minoccurs="0" name="characterval" type="xs:unsignedshort" /> <xs:element minoccurs="0" name="director" type="xs:string" /> <xs:element name="doubleval" type="xs:double" /> <xs:element name="floatval" type="xs:float" /> <xs:element name="intval" type="xs:int" /> <xs:element name="longval" type="xs:long" /> <xs:element minoccurs="0" name="movieid" type="xs:string" /> <xs:element minoccurs="0" name="posterimgbytearray" type="xs:base64binary" />

<xs:element name="shortval" type="xs:short" /> <xs:element minoccurs="0" name="title" type="xs:string" /> </xs:sequence> <xs:complextype name="savemovieresponse"> <xs:sequence> <xs:element name="return" type="xs:boolean" /> </xs:sequence> <xs:complextype name="findmoviemapalllist"> <xs:sequence /> <xs:complextype name="findmoviemapalllistresponse"> <xs:sequence> <xs:element maxoccurs="unbounded" minoccurs="0" name="return" type="tns:movie" /> </xs:sequence> <xs:complextype name="testannotationmethodinclude"> <xs:sequence /> <xs:complextype name="testannotationmethodincluderesponse"> <xs:sequence /> <xs:complextype name="methodc"> <xs:sequence /> <xs:complextype name="methodd"> <xs:sequence> <xs:element minoccurs="0" name="movieannotationwebparam" type="xs:string" /> </xs:sequence> <xs:complextype name="methoddresponse"> <xs:sequence> <xs:element minoccurs="0" name="return" type="xs:string" /> </xs:sequence> <xs:complextype name="methoda"> <xs:sequence /> <xs:complextype name="methodaresponse"> <xs:sequence /> <xs:complextype name="findmoviemapall"> <xs:sequence /> <xs:complextype name="findmoviemapallresponse"> <xs:sequence> <xs:element minoccurs="0" name="return" type="tns:stringmoviemap" /> </xs:sequence> <xs:complextype name="stringmoviemap"> <xs:sequence> <xs:element maxoccurs="unbounded" minoccurs="0" name="entry" type="tns:identifiedmovie" />

</xs:sequence> <xs:complextype name="identifiedmovie"> <xs:sequence> <xs:element name="movieid" type="xs:string" /> <xs:element minoccurs="0" name="movie" type="tns:movie" /> </xs:sequence> </xs:schema> </wsdl:types> <wsdl:message name="findmoviemapall"> <wsdl:part element="ns1:findmoviemapall" name="parameters" /> <wsdl:message name="savemovieresponse"> <wsdl:part element="ns1:savemovieresponse" name="parameters" /> <wsdl:message name="testannotationmethodincluderesponse"> <wsdl:part element="ns1:testannotationmethodincluderesponse" name="parameters" /> <wsdl:message name="methoda"> <wsdl:part element="ns1:methoda" name="parameters" /> <wsdl:message name="findmoviemapalllist"> <wsdl:part element="ns1:findmoviemapalllist" name="parameters" /> <wsdl:message name="methodc"> <wsdl:part element="ns1:methodc" name="parameters" /> <wsdl:message name="findmoviemapallresponse"> <wsdl:part element="ns1:findmoviemapallresponse" name="parameters" /> <wsdl:message name="methoddresponse"> <wsdl:part element="ns1:methoddresponse" name="parameters" /> <wsdl:message name="testannotationmethodinclude"> <wsdl:part element="ns1:testannotationmethodinclude" name="parameters" /> <wsdl:message name="methodaresponse"> <wsdl:part element="ns1:methodaresponse" name="parameters" /> <wsdl:message name="findmoviemapalllistresponse"> <wsdl:part element="ns1:findmoviemapalllistresponse" name="parameters" /> <wsdl:message name="methodd"> <wsdl:part element="ns1:methodd" name="parameters" /> <wsdl:message name="savemovie"> <wsdl:part element="ns1:savemovie" name="parameters" /> <wsdl:porttype name="movieservice"> <wsdl:operation name="savemovie"> <wsdl:input message="ns1:savemovie" name="savemovie" /> <wsdl:output message="ns1:savemovieresponse" name="savemovieresponse" />

<wsdl:operation name="findmoviemapalllist"> <wsdl:input message="ns1:findmoviemapalllist" name="findmoviemapalllist" /> <wsdl:output message="ns1:findmoviemapalllistresponse" name="findmoviemapalllistresponse" /> <wsdl:operation name="testannotationmethodinclude"> <wsdl:input message="ns1:testannotationmethodinclude" name="testannotationmethodinclude" /> <wsdl:output message="ns1:testannotationmethodincluderesponse" name="testannotationmethodincluderesponse" /> <wsdl:operation name="methodc"> <wsdl:input message="ns1:methodc" name="methodc" /> <wsdl:operation name="methodd"> <wsdl:input message="ns1:methodd" name="methodd" /> <wsdl:output message="ns1:methoddresponse" name="methoddresponse" /> <wsdl:operation name="methoda"> <wsdl:input message="ns1:methoda" name="methoda" /> <wsdl:output message="ns1:methodaresponse" name="methodaresponse" /> <wsdl:operation name="findmoviemapall"> <wsdl:input message="ns1:findmoviemapall" name="findmoviemapall" /> <wsdl:output message="ns1:findmoviemapallresponse" name="findmoviemapallresponse" /> </wsdl:porttype> </wsdl:definitions> 나. Client 설정 - Client 설정을위하여다음과같은디렉터리구조를가짂다. - 실제로구축을하는코드는아래 com.mycompany.webservice.client에있는두개의 java파일이며, 나머지는 wsdl에의해서생성되는 stub 및 domain class이다.

- 구현되는코드는다음과같다. 특정파일을젂송하고저장하는 savemovie 등의함수를 포함하고있다. package com.mycompany.webservice.client; import java.io.file; import java.io.fileinputstream; import java.io.ioexception; import java.io.inputstream; import org.springframework.beans.factory.xml.xmlbeanfactory; import org.springframework.core.io.classpathresource; import egovframework.lab.web.ws.jaxws.movie; import egovframework.lab.web.ws.jaxws.movieservice; import egovframework.lab.web.ws.jaxws.stringmoviemap; public class WSClient4Jaxws { public static void main(string[] args) throws Exception { XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("client-context-jaxws.xml")); // CalcInterface cal = (CalcInterface) factory.getbean("client"); // System.out.println("cal.result(1, 2) = " + cal.result(1, 2)); // MovieService movie = (MovieService)

// factory.getbean("movieservicesimple"); MovieService movieservice = (MovieService) factory.getbean("moviejclient"); System.out.println("movieService.methodA() called "); System.out.println("movieService.methodD() called " + movieservice.methodd("good")); //StringMoveMap 을이용하여지원되지않는 Map 타입구현. @SuppressWarnings("unused") StringMovieMap rm = (StringMovieMap) movieservice.findmoviemapall(); // 파일첨부하여 Movie 객체에넣어보내기. String dir = "C:/egovframeworkSample/workspace_template/wsclient/"; Movie moviewithfile = new Movie(); moviewithfile.settitle("skysamplejaxws"); File afile = new File(dir + "file.pdf"); //attach a file moviewithfile.setposterimgbytearray(getbytesfromfile(afile)); moviewithfile.setposterimgdatahandler(null); //remote method 실행. boolean success = movieservice.savemovie(moviewithfile); System.out.println("sending file? =>" + success); { /* * 파일을 byte[] 형태로가져오기. */ public static byte[] getbytesfromfile(file file) throws IOException InputStream is = new FileInputStream(file); // Get the size of the file long length = file.length(); if (length > Integer.MAX_VALUE) { // File is too large // Create the byte array to hold the data byte[] bytes = new byte[(int) length]; // Read in the bytes int offset = 0; int numread = 0; while (offset < bytes.length && (numread = is.read(bytes, offset, bytes.length - offset)) >= 0) { offset += numread; // Ensure all the bytes have been read in

if (offset < bytes.length) { throw new IOException("Could not completely read file " + file.getname()); // Close the input stream and return bytes is.close(); return bytes; - 설정에필요한 src/main/resources 의파일들은아래 PKI Security 설정부분에설명되어 있다. 다. PKI 방식 Security 적용 1 Security 적용을위한 CXF Security 라이브러리설정확인 <dependency> <groupid>org.apache.cxf</groupid> <artifactid>cxf-rt-ws-security</artifactid> <version>${cxf.version</version> </dependency> 2 PKI 키생성 - PKI 설정을위하여 keytool 을홗용하여 key-pair 를생성하고, 생성된 key 를 export 한다. - 생성된키는테스트를위한용도이고, 사용기간에제한이있음 ( 유효하지않다는메시지가출력될경우키를재생성해야함 ) keytool -genkey -alias myservicekey -keyalg RSA -sigalg SHA1withRSA -keypass skpass -storepass sspass -keystore servicekeystore.jks -dname "cn=localhost" keytool -genkey -alias myclientkey -keyalg RSA -sigalg SHA1withRSA -keypass ckpass -storepass cspass -keystore clientkeystore.jks -dname "cn=clientuser" keytool -genkey -alias unauthorizedkey -keyalg RSA -sigalg SHA1withRSA -keypass ukpass -storepass uspass -keystore unauthidentity.jks -dname "cn=unauthorizedkey" keytool -export -rfc -keystore clientkeystore.jks -storepass cspass -alias myclientkey -file MyClient.cer keytool -import -trustcacerts -keystore servicekeystore.jks -storepass sspass -alias myclientkey -file MyClient.cer -noprompt keytool -export -rfc -keystore servicekeystore.jks -storepass sspass -alias myservicekey -file MyService.cer keytool -import -trustcacerts -keystore clientkeystore.jks -storepass cspass -alias myservicekey -file MyService.cer -noprompt 3 PKI 키설정 - PKI 설정을위하여 Provider 와 Consumer 양쪽에설정이필요함 - 먼저서버설정을위하여 servicekeystore.jks 를 Server 프로젝트 src/main/resources 밑에 copy 한다. - 파일설정을위한 servicekeystore.properties 를생성 (src/main/resources) org.apache.ws.security.crypto.provider=org.apache.ws.security.components.cr ypto.merlin

org.apache.ws.security.crypto.merlin.keystore.type=jks org.apache.ws.security.crypto.merlin.keystore.password=sspass org.apache.ws.security.crypto.merlin.keystore.alias=myservicekey org.apache.ws.security.crypto.merlin.file=servicekeystore.jks - 마찬가지로 clientkeystore.jks 는 client 프로젝트 src/main/resources 밑에 copy 한다. - 파일설정을위한 clientkeystore.properties 를생성 (src/main/resources) org.apache.ws.security.crypto.provider=org.apache.ws.security.components.cr ypto.merlin org.apache.ws.security.crypto.merlin.keystore.type=jks org.apache.ws.security.crypto.merlin.keystore.password=cspass org.apache.ws.security.crypto.merlin.keystore.alias=myclientkey org.apache.ws.security.crypto.merlin.file=clientkeystore.jks 4 설정파일 ( 서버설정 : spring-cxf.xml, client 설정 : client-context-jaxws.xml) - 서버설정을위하여 Endpoint 설정과함께 Security 설정수행함 - Security 적용은 endpoint 에서입력과출력시에 interceptor 를실행하여처리를수행하며, 입력시에는암호화된메시지를복화하여비즈니스로직을처리하고, 처리된결과값이 출력되는시점에서암호화를하여 client 에게젂달하게됨 - 다음은 server 쪽설정을수행하는 spring-cxf.xml 의설정이다. <?xml version="1.0" encoding="utf-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:simple="http://cxf.apache.org/simple" 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/simple http://cxf.apache.org/schemas/simple.xsd"> <import resource="classpath:meta-inf/cxf/cxf.xml" /> <import resource="classpath:meta-inf/cxf/cxf-extension-soap.xml" /> <import resource="classpath:meta-inf/cxf/cxf-servlet.xml" /> <!-- jaxws Frontend --> <jaxws:endpoint id="mycalc" implementor="egovframework.lab.web.ws.jaxws.calcimpl" address="/mycalc" /> <!--jaxws Frontend --> <jaxws:endpoint id="myjaxws" implementor="egovframework.lab.web.ws.jaxws.movieserviceimpl" address="/myjaxws"> <jaxws:properties> <entry key="mtom-enabled" value="true" /> </jaxws:properties> <!-- 인증 Interceptors --> <jaxws:ininterceptors> <ref bean="timestampsignencrypt_request" /> </jaxws:ininterceptors> <jaxws:outinterceptors> <ref bean="timestampsignencrypt_response" /> </jaxws:outinterceptors> </jaxws:endpoint> <bean id="egovframework.lab.web.ws.simple.movieservice"

class="egovframework.lab.web.ws.simple.movieserviceimpl" /> <!-- WSS4JInInterceptor for decrypting and validating the signature of the SOAP request. --> <bean id="timestampsignencrypt_request" class="org.apache.cxf.ws.security.wss4j.wss4jininterceptor"> <constructor-arg> <map> <entry key="action" value="timestamp Signature Encrypt" /> <entry key="signaturepropfile" value="servicekeystore.properties" /> <entry key="decryptionpropfile" value="servicekeystore.properties" /> <entry key="passwordcallbackclass" value="com.mycompany.webservice.service.servicekeystorepasswordcallback" /> </map> </constructor-arg> </bean> <!-- WSS4JOutInterceptor for encoding and signing the SOAP response. --> <bean id="timestampsignencrypt_response" class="org.apache.cxf.ws.security.wss4j.wss4joutinterceptor"> <constructor-arg> <map> <entry key="action" value="timestamp Signature Encrypt" /> <entry key="user" value="myservicekey" /> <entry key="signaturepropfile" value="servicekeystore.properties" /> <entry key="encryptionpropfile" value="servicekeystore.properties" /> <entry key="encryptionuser" value="myclientkey" /> <entry key="signaturekeyidentifier" value="directreference" /> <entry key="passwordcallbackclass" value="com.mycompany.webservice.service.servicekeystorepasswordcallback" /> <entry key="signatureparts" value="{element{http://docs.oasis- open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility- 1.0.xsdTimestamp;{Element{http://schemas.xmlsoap.org/soap/envelope/Body" /> <entry key="encryptionparts" value="{element{http://www.w3.org/2000/09/xmldsig#signature;{content{http ://schemas.xmlsoap.org/soap/envelope/body" /> <entry key="encryptionsymalgorithm" value="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" /> </map> </constructor-arg> </bean> </beans> - server에서의설정과비슷한형태로 client 설정이이루어지게됨. client 설정을위하여 proxy설정 (client-context-jaxws.xml) 과함께 Security설정수행함 - Security 적용은 proxy에서입력과출력시에 interceptor를실행하여처리를수행하며, server에서의처리와반대로처리가되어입력시에는암호화된메시지를암호하여 server로젂송하고, 처리된결과값을젂달받아출력되는시점에서복호화를하여비즈니스로직에게젂달하게됨

- 다음은 client 설정을수행하는 client-context-jaxws.xml 의내용이다. <?xml version="1.0" encoding="utf-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:simple="http://cxf.apache.org/simple" xmlns:http="http://cxf.apache.org/transports/http/configuration" 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/simple http://cxf.apache.org/schemas/simple.xsd"> <!-- JAX-WS frontend --> <bean id="client" class="egovframework.lab.web.ws.jaxws.calcinterface" factory-bean="clientfactory" factory-method="create" /> <bean id="clientfactory" class="org.apache.cxf.jaxws.jaxwsproxyfactorybean"> <property name="serviceclass" value="egovframework.lab.web.ws.jaxws.calcinterface" /> <property name="address" value="http://localhost:8080/ws/ws/mycalc" /> </bean> <!-- JAX-WS frontend :: 파일첨부하여젂송 (with 암호화 --> <bean id="moviejclient" class="egovframework.lab.web.ws.jaxws.movieservice" factory-bean="movieclientfactory" factory-method="create" /> <bean id="movieclientfactory" class="org.apache.cxf.jaxws.jaxwsproxyfactorybean"> <property name="serviceclass" value="egovframework.lab.web.ws.jaxws.movieservice" /> <property name="address" value="http://localhost:8080/ws/ws/myjaxws" /> <!-- 암호화 --> <property name="ininterceptors"> <list> <ref bean="timestampsignencrypt_response" /> </list> </property> <property name="outinterceptors"> <list> <ref bean="timestampsignencrypt_request" /> </list> </property> </bean> <!-- Interceptor 정의 --> <!-- This bean is an Out interceptor which will add a timestamp, sign the timestamp and body, and then encrypt the timestamp and body. It uses 3DES as the symmetric key algorithm.

--> <bean class="org.apache.cxf.ws.security.wss4j.wss4joutinterceptor" id="timestampsignencrypt_request"> <constructor-arg> <map> <entry key="action" value="timestamp Signature Encrypt" /> <entry key="user" value="myclientkey" /> <entry key="signaturepropfile" value="clientkeystore.properties" /> <entry key="encryptionpropfile" value="clientkeystore.properties" /> <entry key="encryptionuser" value="myservicekey" /> <entry key="signaturekeyidentifier" value="directreference" /> <!----> <entry key="passwordcallbackclass" value="com.mycompany.webservice.client.clientkeystorepasswordcallbac k" /> <entry key="signatureparts" value="{element{http://docs.oasis- open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility- 1.0.xsdTimestamp;{Element{http://schemas.xmlsoap.org/soap/envelope/Body" /> <entry key="encryptionparts" value="{element{http://www.w3.org/2000/09/xmldsig#signature;{conte nt{http://schemas.xmlsoap.org/soap/envelope/body" /> <entry key="encryptionsymalgorithm" value="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" /> </map> </constructor-arg> </bean> <!-- This bean is an In interceptor which will validate a signed, encrypted response, and timestamp it. --> <bean class="org.apache.cxf.ws.security.wss4j.wss4jininterceptor" id="timestampsignencrypt_response"> <constructor-arg> <map> <entry key="action" value="timestamp Signature Encrypt" /> <entry key="signaturepropfile" value="clientkeystore.properties" /> <entry key="decryptionpropfile" value="clientkeystore.properties" /> <entry key="passwordcallbackclass" value="com.mycompany.webservice.client.clientkeystorepasswordcallbac k" /> </map> </constructor-arg> </bean> </beans>