내용 목차
본 장에서는 전송 수준과 메시지 수준의 웹 서비스 보안에 대해 자세히 살펴보고 어떻게 JEUS 웹 서비스에서 이러한 보안 적용을 하는지에 대해 살펴보기로 한다.
웹 서비스에 보안을 적용하기 위해서는 전통적으로 다음과 같은 2가지 방식이 존재한다.
전송 수준 보안(Transport-level Security)
SSL을 이용하여 클라이언트와 웹 서비스 사이의 연결 보안을 보장한다.
메시지 수준 보안
SOAP 메시지를 전자 서명이나 암호화한다.
전송 수준 보안을 적용하려면 클라이언트와 JEUS 서버 간의 연결을 SSL을 이용하여 안전하게 할 수 있다. 그러나 이러한 방식은 연결 자체만을 안전하게 하며 클라이언트와 JEUS 서버 사이에 라우터나 메시지 큐와 같은 매개체(Intermediary)가 있다면 매개체는 SOAP 메시지를 암호화되지 않은 읽히기 쉬운 텍스트 문서 형태로 가질 수 있다. 또한 전송 수준 보안은 전체적인 메시지를 다루므로 메시지 일부의 보안 적용이 불가능하다.
메시지 수준 보안은 SSL의 보안의 장점을 포함하면서 부가적인 유연성을 제공한다. 메시지 수준 보안은 메시지 전달 과정에서 하나 이상의 매개체가 존재하더라도 보안이 유지되는 엔드-투-엔드(End-to-End)보안이며, 연결 자체가 보안이 유지된다기 보다는 SOAP 메시지 자체의 서명과 암호화를 의미한다. 또한 부분적인 서명과 암호화가 가능하다는 장점이 있다.
웹 서비스의 전송 수준 보안이라는 의미는 웹 서비스 클라이언트 응용 프로그램과 웹 서비스 간의 연결을 SSL을 이용하여 안전하게 하는 것을 의미한다. 전체적인 절차는 다음과 같다.
JEUS 서버의 SSL을 설정한다.
클라이언트 응용 프로그램의 SSL을 설정한다.
JEUS 서버에서의 SSL 설정은 "JEUS Web Container 안내서"를 참조하도록 하며, 웹 서비스 개발 부분은 추가 작업이 필요하지 않다.
응용 프로그램의 SSL 설정은 다음과 같은 절차를 따른다.
인증서를 가져온다(인터넷 익스플로러 등을 통해 인증서를 로컬 디렉터리에 저장한다).
가져온 인증서를 키스토어에 저장한다.
wsimport를 이용하여 wsdl로부터 Stub을 생성하려고 하거나 클라이언트에서 웹 서비스를 호출하기 위해 클라이언트를 실행하려고 할 때 시스템 프로퍼티 값을 다음과 같이 설정한다.
–Djavax.net.ssl.trustStore=keystore_name
–Djavax.net.ssl.trustStorePassword=keystore_password
wsimport 콘솔 툴을 사용한다면, 추가적으로 다음과 같은 환경변수 설정이 필요하다.
set WSIMPORT_OPTS=-Djavax.net.ssl.trustStore=keystore_name -Djavax.net.ssl.trustStorePassword=keystore_password
JEUS 웹 서비스가 구현하고 있는 웹 서비스 보안에 관한 명세서로는 다음과 같은 것들이 있다.
웹 서비스 보안 정책(WS-Security Policy)
웹 서비스 보안(WS-Security)
웹 서비스 보안 대화(WS-SecureConversation)
웹 서비스 신뢰(WS-Trust)
본 절에서는 각각의 명세서들에 대해 그 의미와 시나리오를 알아보도록 한다.
웹 서비스 보안 정책(Web Service Security Policy) 명세는 어떻게 메시지가 보안화되어 이동되는지 설명하는 전제(assertion)들을 정의한다. 이러한 전제들은 토큰, 암호화 기법, 사용되는 메커니즘, 전송 보안 등의 정책들을 포괄하는 유연성을 따른다.
이러한 웹 서비스 보안 정책은 웹 서비스 메시지 수준 보안을 구현할 때 핵심적인 요소이다. JEUS 웹 서비스에서는 여러 가지 웹 서비스 메시지 수준 보안을 위한 시나리오별 예제들을 제공한다. 이러한 시나리오별 예제의 웹 서비스 보안 정책을 적용한 정책 파일들은 여러 가지 웹 서비스의 메시지 보안을 적용하는 데 도움이 될 것이다.
웹 서비스 보안(Web Service Security) 명세는 메시지의 XML 서명을 이용한 데이터 무결성과 XML 암호화를 이용한 데이터 비밀성 두 가지를 실현하여 안전한 웹 서비스를 구현할 때 사용되는 확장된 SOAP element들을 정의하고 있다.
이러한 웹 서비스 보안 명세를 이용한 웹 서비스 보안 시나리오는 다음의 세 가지 정도로 생각해 볼 수 있다.
이 예제는 대칭 바인딩(Symmetric Binding)을 통한 메시지 보안 예제이다. 앞서 설명한 것과 마찬가지로 대칭 바인딩에서는 클라이언트와 서버가 암호화 키와 서명에 동일한 인증서 정보를 사용한다. 이 예제에서는 그 인증서 정보로써 서버의 인증서를 이용한다. 이 때 클라이언트는 자신이 누구인지를 서버에 인증 받을 방법이 따로 존재하지 않기 때문에 부가적으로 사용자명 토큰을 사용한다.
다음은 사용자명 인증(Username Authentication)의 시나리오이다.
클라이언트는 대칭 키를 생성한 후 이를 이용해 요청 메시지를 암호화 및 서명을 한다. 이때 서버의 공개 키를 이용하여 대칭 키를 함께 메시지에 담아 보낸다. 추가적으로 사용자명과 비밀번호 정보를 함께 보낸다.
서버는 서버의 개인 키를 이용하여 대칭 키를 해독한 뒤 이를 이용하여 클라이언트의 요청 메시지를 복호화하고 서명을 검증한다. 추가적으로 사용자명과 비밀번호를 통해 클라이언트를 인증한다.
서버는 다시 그 대칭 키를 통해 응답 메시지를 서명 및 암호화한다. 이때 대칭 키를 따로 클라이언트로 전송하지는 않는다.
클라이언트는 가지고 있던 대칭 키를 이용하여 서버의 응답 메시지를 해석하고 서명을 확인한다.
다음은 키스토어 설정 정보이다.
구분 | 설명 |
---|---|
클라이언트 | 서버의 공개 키가 담긴 키스토어 |
서버 | 서버의 개인 키가 담긴 키스토어 |
이 예제는 비대칭 바인딩, 상호 인증서를 통한 메시지 보안 예제이다. 대칭 바인딩과 달리 비대칭 바인딩에서는 클라이언트와 서버가 암호화 키와 서명에 서로 다른 인증서 정보를 사용한다. 서로 자신의 개인 키로 서명을 하고 인증서 정보를 넘겨줌으로, 서로 서명을 검증할 때 상대편이 누구인지를 인증할 수 있다.
다음은 상호 인증 보안 (Mutual Certificates Security)의 시나리오이다.
클라이언트는 클라이언트의 개인 키로 메시지에 서명을 하고 하나의 대칭 키를 생성해서 메시지를 암호화한 후, 그 대칭 키를 서버의 공개 키를 이용하여 암호화하여 메시지와 함께 서버에게 요청 메시지를 보낸다. 이때 인증 역할을 하게 될 클라이언트의 인증서를 함께 보낸다.
서버는 서버의 개인 키를 이용하여 대칭 키를 꺼낸후 암호화된 메시지를 해석한다. 인증서를 통해 인증을 하고 클라이언트의 공개 키로 서명을 검증한다.
서버는 서버의 개인 키로 메시지에 서명을 하고 하나의 대칭 키를 생성해서 메시지를 암호화한 후 그 대칭 키를 클라이언트의 공개 키를 이용하여 암호화하며 메시지와 함께 클라이언트에게 응답 메시지를 보낸다. 이때 인증 역할을 하게 될 서버의 인증서는 함께 보내지 않는다.
클라이언트는 클라이언트의 개인 키를 이용하여 대칭 키를 꺼낸후 암호화된 메시지를 해석한다. 서버의 공개 키로 서명을 확인한다.
다음은 키스토어 설정 정보이다.
구분 | 설명 |
---|---|
클라이언트 | 클라이언트의 개인키와 서버의 공개키가 담긴 키스토어 |
서버 | 서버의 개인키와 클라이언트의 공개키가 담긴 키스토어 |
이 예제는 SAML 토큰을 어떻게 SOAP 메시지 헤더에 포함시켜 보내는지에 대해 설명한다.
실제 웹 서비스에서 SAML 토큰을 이용한 서비스를 하기 위해서는 이러한 SAML 토큰을 생성하는 SAML 토큰 프레임워크가 필요할 것이다. 여기서는 단순히 핸들러를 통해 SAML 토큰을 텍스트로 생성해서 보내는 예를 통해 어떻게 SAML 토큰을 SOAP 메시지 헤더에 포함시키는지에 대해 알 수 있다.
웹 서비스의 발전과 사용자의 활용 빈도가 높아짐에 따라 다양한 웹 애플리케이션 간에 보안 및 인증 정보를 교환할 필요성이 높아지고 이에 따른 교환 표준이 필요하다. 이와 같은 표준을 제공하기 위해 탄생한 언어가 SAML(Security Assertions Mark-up Language)이다. SAML에서 제공하는 기능은 다음과 같다.
사용자 보안 정보에 대한 XML 포맷을 제공하고 이러한 정보를 요청 및 전송하기 위한 포맷을 제공한다.
SOAP 같은 프로토콜에서 이러한 메시지를 사용하는 방법을 정의한다.
웹 SSO와 같이 일반적인 특정 이용 사례에 대해 자세한 메시지 교환 방법을 지정한다.
사용자의 신원을 Export시키지 않고 사용자 속성을 결정하는 기능을 비롯하여 여러 가지 개인 정보 보호 메커니즘을 지원한다.
UNIX, Microsoft Windows, X.509, LDAP, DCE, XCML 등 널리 사용되는 기술에서 제공하는 포맷으로 ID 정보를 처리하는 방법을 제공한다.
메타 데이터 스키마를 수식화하여 참여하는 시스템에서 지원하는 SAML 옵션과 통신할 수 있는 기능 제공한다.
다음은 SAML의 시나리오이다.
클라이언트는 SAML 토큰을 SOAP 메시지 헤더에 포함하여 SSL 설정을 통하여 메시지를 보낸다.
서버는 SOAP 메시지 헤더에 포함된 SAML 토큰을 해석하고 응답 메시지를 보낸다.
모든 클라이언트와 서버의 메시지 교환은 JEUS 서버의 SSL 설정을 통해 이루어진다.
웹 서비스 보안 대화(Web Service Secure Conversation) 명세는 서비스 제공자와 클라이언트 간의 보안 컨텍스트 생성 및 공유를 정의한다. 보안 컨텍스트는 메시지를 교환할 때 생기는 간접비용(overhead)을 줄이기 위해 사용된다. 이 명세는 보다 나은 메시지 수준의 보안과 보다 효율적인 다중 메시지 교환을 제공하기 위한 표준을 정의한다.
이 명세를 따르고 있는 JEUS 웹 서비스는 다중 메시지 교환을 위한 보안 방식이 정의되는 기본 메커니즘을 제공하고 더욱 더 효율적인 키나 새로운 키 재료와 함께 컨텍스트가 수립되도록 한다. 이러한 접근은 전체적인 성능과 다음에 따르는 메시지 교환의 보안성을 향상시킨다.
대칭 바인딩에서는 메시지를 여러 번 주고받을 때마다 암호화키를 매번 생성해야 한다. 따라서 메시지를 여러 번 주고받는 시나리오에서는 적합하지 않다고 볼 수 있다. 이 예제에서는 보안 대화(Secure Conversation)를 통해 첫 메시지를 주고받기 전 핸드쉐이킹(handshaking) 과정을 통해 비대칭 바인딩으로 서로 SecureContext를 수립하고 이후 실제 메시지를 여러 번 주고받을 때는 수립한 SecureContext를 이용하여 대칭 바인딩과 같이 서명과 암호화에 사용하게 된다. 인증 과정은 처음 비대칭 바인딩을 통한 SecureContext 수립과정에서 거치게 된다.
다음은 웹 서비스 보안 대화의 시나리오이다.
클라이언트는 자신의 인증서와 SecureContext 정보를 자신의 인증서를 이용해 서명을 하고 서버의 공개 키로 암호화 하여 서버에 전송한다(비대칭 바인딩).
서버는 자신의 개인 키로 클라이언트의 메시지를 복호화하고 클라이언트 서명을 검증하면서 인증 절차를 거친후 SecureContext 수립 메시지로 응답한다(비대칭 바인딩).
이후 클라이언트와 서버는 메시지를 주고받을 때 이 SecureContext 정보를 통해 암호화 및 서명을 한다(대칭 바인딩).
다음은 키스토어 설정 정보이다.
구분 | 설명 |
---|---|
클라이언트 | 클라이언트의 개인 키와 서버의 공개 키가 담긴 키스토어 |
서버 | 서버의 개인 키와 클라이언트의 공개 키가 담긴 키스토어 |
웹 서비스 보안을 사용하는 메시지 교환 방식에서는 서비스와 클라이언트 간에 보안 정보 공유를 위해 사용되는 보안 토큰에 대해 이미 합의되어야 하지만, 이러한 사전 합의가 이루어지지 않는 경우 메시지 교환 이전에 신뢰 관계(trust relationship)가 성립되어야 한다. 이러한 것을 웹 서비스 신뢰(Web Service Trust)라고 하며 JEUS 웹 서비스는 이를 지원하고 있다.
웹 서비스 신뢰는 서버와 클라이언트가 서로 다른 형태의 보안 토큰 또는 서로 다른 도메인의 보안 토큰을 사용해서 서로를 인증하지 못하는 상황일 때 사용할 수 있다. 이러한 클라이언트와 서버의 상이한 보안 토큰때문에 서로를 인증하지 못하는 상황은, 클라이언트와 서버 사이에 각각의 인증 역할을 중계해 주는 또 다른 웹 서비스가 존재하여 이를 해결하도록 한다. 이러한 웹 서비스는 통상적으로 STS(Security Token Service)라고 한다.
보다 구체적으로, 아래의 그림과 같이 Requestor는 웹 서비스와 통신하기 전에 웹 서비스가 자신을 인증할 수 있도록 하는 보안 토큰을 STS로부터 동적으로 부여받는다. 부여받은 보안 토큰을 통해 Requestor는 웹 서비스에게 실제로 보내려는 메시지에 STS로 부여받은 보안 토큰을 함께 실어 보내게 되며 웹 서비스는 Requestor를 인증(신뢰)할 수 있다.
*출처 http://docs.oasis-open.org/ws-sx/ws-trust/200512/ws-trust-1.3-os.html
웹 서비스 신뢰는 다음의 관계를 갖는다.
클라이언트와 서버는 서로 직접적인 신뢰 관계가 없다.
클라이언트와 STS는 서로 신뢰 관계가 있다.
STS와 서버는 서로 신뢰 관계가 있다.
여기서는 WS-Trust를 인증에 관해 사용하는 예에 대해 살펴본다.
서로 다른 토큰, 즉 신뢰할 수 없는 관계의 인증서는 STS를 통해 SAML 토큰이라는 다른 형태로 변환되어 요청자를 신뢰할 수 없는 응답자가 STS를 통하여 인증할 수 있다.
다음은 웹 서비스 신뢰의 시나리오이다.
클라이언트는 자신의 인증서, 사용자명, 암호와 함께 실제 메시지를 전달할 서버에 대한 SAML 인증서 발급을 STS에 요청한다.
STS는 클라이언트를 인증한 후 SAML 인증서를 발급한다.
클라이언트는 SAML 인증서와 함께 서버에 메시지를 보낸다.
서버는 SAML 인증서를 통해 클라이언트를 신뢰하고 비지니스 로직을 수행한다.
다음은 키스토어 설정 정보이다.
구분 | 설명 |
---|---|
클라이언트 | 1. 클라이언트의 개인 키와 서버의 공개 키가 담긴 키스토어 2. 클라이언트의 개인 키와 STS 서버의 공개 키가 담긴 키스토어 |
서버 | 서버의 개인 키와 클라이언트의 공개 키가 담긴 키스토어 |
STS 서버 | 서버의 개인 키와 클라이언트의 공개 키가 담긴 키스토어 |
본 절에서는 JEUS 웹 서비스 메시지 수준 보안의 여러 가지 시나리오 예제에서 공통적으로 적용되는 설정법에 대해 알아본다. 이후 각각의 시나리오에 대한 설정법을 자세히 살펴볼 것이다. 실제 여러 가지 시나리오 예제에서 동작하는 것에 대해서는 샘플을 참조한다.
각 시나리오별 메시지 보안 설정 예제의 웹 서비스와 클라이언트의 비즈니스 로직은 모두 동일하다.
다음은 'endpoint-policy-subject', 'operation-policy-subject', 'input(output)-message-policy-subject'에 공통적으로 들어가는 보안 설정들에 대한 설명이다.
'keystore', 'truststore' element의 설정
'security-policy' 하위의 element 중 하나인 'keystore', 'truststore' element는 그 'security-policy' element의 'security-binding'의 보안 설정에 따라 능동적으로 설정해야 한다.
'keystore-filename'에 들어가는 키스토어 파일에 대한 설정은 절대 경로 혹은 상대 경로를 포함한 실제 키스토어 파일의 위치를 지정한다. 상대 경로로 지정할 때는 서비스 구현 클래스가 포함된 classes 디렉터리 하위의 META-INF 디렉터리에 키스토어 파일이 위치해야 한다.
[예 16.1] << jeus-webservices-config.xsd >>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <xs:schema xmlns="http://www.tmaxsoft.com/xml/ns/jeus" targetNamespace="http://www.tmaxsoft.com/xml/ns/jeus" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified" version="6.0"> ...... <xs:complexType name="keyTruststoreType"> <xs:choice> <xs:element name="keystore-file" type="keyTruststoreFileType" /> <xs:element name="keystore-callbackhandler" type="xs:string" /> </xs:choice> </xs:complexType> <xs:complexType name="keyTruststoreFileType"> <xs:sequence> <xs:element name="alias" type="xs:string" /> <xs:element name="key-type" type="xs:string" minOccurs="0" default="JKS" /> <xs:element name="keystore-password" type="xs:string" /> <xs:element name="keystore-filename" type="xs:string" /> </xs:sequence> </xs:complexType> ...... </xs:schema>
'include-token' 속성 설정
'include-token' 속성은 메시지에 토큰을 포함할 것인지의 여부를 설정한다. X509 토큰에서 사용되는 예는 다음과 같다.
[예 16.2] << jeus-webservices-config.xsd >>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <xs:schema xmlns="http://www.tmaxsoft.com/xml/ns/jeus" targetNamespace="http://www.tmaxsoft.com/xml/ns/jeus" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified" version="6.0"> ...... <xs:complexType name="x509TokenType"> <xs:sequence> <xs:element name="include-token" type="xs:boolean" minOccurs="0" default="false" /> </xs:sequence> </xs:complexType> ...... </xs:schema>
그 밖의 다른 element 설정에 대한 자세한 설명은 'jeus-webservices-config.xsd' 스키마 및 reference book, sample 예제를 참조한다.
Java 클래스로부터 웹 서비스 메시지 보안을 구현하기 위해서는 다음과 같이 wsgen 콘솔 툴의 -policy 기능을 이용하여 웹 서비스를 구성한다.
C:\>wsgen fromjava.server.AddNumbersImpl -d web/WEB-INF -policy service-config.xml
'-policy'의 인자로 사용되는 service-config.xml를 구성하는 방법은 service-config.xml을 위한 JEUS 보안 정책 스키마인 jeus-webservices-config.xsd에 대해 알아봐야 한다.
JEUS 보안 정책 스키마는 아래와 같이 크게 3가지 부분, 'endpoint-policy-subject', 'operation-policy-subject', 'input(output)-message-policy-subject' element에 보안 설정을 할 수 있다. 'endpoint-policy-subject', 'operation-policy-subject', 'input(output)-message-policy-subject'에 대한 세부적인 내용은 계속되는 절에서 자세히 설명한다.
[예 16.3] << jeus-webservices-config.xsd >>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <xs:schema xmlns="http://www.tmaxsoft.com/xml/ns/jeus" targetNamespace="http://www.tmaxsoft.com/xml/ns/jeus" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified" version="6.0"> ...... <xs:element name="web-services-config" type="web-services-configType" /> <xs:complexType name="web-services-configType"> <xs:choice> ...... <xs:element name="policy" type="policy-configType" maxOccurs="unbounded" /> </xs:choice> </xs:complexType> <xs:complexType name="policy-configType"> <xs:sequence> <xs:element name="endpoint-policy-subject" type="endpointPolicySubjectType" maxOccurs="unbounded" /> </xs:sequence> </xs:complexType> <xs:complexType name="endpointPolicySubjectType"> <xs:sequence> ...... <xs:element name="security-policy" type="endpointSecurityPolicyType" minOccurs="0" /> <xs:element name="operation-policy-subject" type="operationPolicySubjectType" minOccurs="0" maxOccurs="unbounded" /> </xs:sequence> </xs:complexType> <xs:complexType name="operationPolicySubjectType"> <xs:sequence> <xs:element name="security-policy" type="operationSecurityPolicyType" minOccurs="0" /> ...... <xs:element name="input-message-policy-subject" type="messagePolicySubjectType" minOccurs="0" /> <xs:element name="output-message-policy-subject" type="messagePolicySubjectType" minOccurs="0" /> </xs:sequence> </xs:complexType> <xs:complexType name="messagePolicySubjectType"> <xs:sequence> <xs:element name="security-policy" type="messageSecurityPolicyType" minOccurs="0" /> </xs:sequence> </xs:complexType> ...... </xs:schema>
이 3가지 element들의 보안 설정 내용은 다음과 같다.
'endpoint-policy-subject' element 보안 설정
서비스 구현 클래스를 단위로 보안 설정을 할 수 있다. 보안 바인딩(비대칭, 대칭) 설정 및 서명 및 암호화, 보안 토큰, WS-Security 버젼 등 메시지 보안에 관한 여러 가지를 설정할 수 있다.
[예 16.4] << jeus-webservices-config.xsd >>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <xs:schema xmlns="http://www.tmaxsoft.com/xml/ns/jeus" targetNamespace="http://www.tmaxsoft.com/xml/ns/jeus" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified" version="6.0"> ...... <xs:complexType name="endpointSecurityPolicyType"> <xs:sequence> <xs:element name="security-binding" type="securityBindingType" minOccurs="0" /> <xs:element name="token" type="supportingTokenType" minOccurs="0" /> <xs:element name="protection" type="protectionType" minOccurs="0" /> ...... </xs:sequence> </xs:complexType> ...... </xs:schema>
'endpoint-policy-subject' element 보안 설정은 서비스 구현 클래스 단위의 보안 설정으로 다음과 같이 크게 3가지로 나뉠 수 있다.
security-binding
다음과 같이 security-binding element 보안 설정은 'transport-binding', 'symmetric-binding', 'asymmetric-binding' 중 하나를 선택할 수 있다.
[예 16.5] << jeus-webservices-config.xsd >>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <xs:schema xmlns="http://www.tmaxsoft.com/xml/ns/jeus" targetNamespace="http://www.tmaxsoft.com/xml/ns/jeus" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified" version="6.0"> ...... <xs:complexType name="securityBindingType"> <xs:sequence> <xs:choice> <xs:element name="transport-binding" type="transportBindingType" /> <xs:element name="symmetric-binding" type="symmetricBindingType" /> <xs:element name="asymmetric-binding" type="asymmetricBindingType" /> </xs:choice> </xs:sequence> </xs:complexType> ...... </xs:schema>
'transport-binding' element 보안 설정
transport-binding element의 보안 설정은 웹 서비스 보안(WS-Security) 명세 외에 다른 전송단, 예를 들어 HTTPS와 같은 것을 이용하여 메시지를 보호하겠다는 것을 나타낸다.
[예 16.6] << jeus-webservices-config.xsd >>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <xs:schema xmlns="http://www.tmaxsoft.com/xml/ns/jeus" targetNamespace="http://www.tmaxsoft.com/xml/ns/jeus" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified" version="6.0"> ...... <xs:complexType name="transportBindingType"> <xs:sequence> <xs:element name="transport-token" type="tokenType" /> <xs:element name="algorithm-suite" type="algorithmSuiteType" minOccurs="0" default="Basic128" /> <xs:element name="layout" type="layoutType" minOccurs="0" default="Lax" /> <xs:element name="timestamp" type="xs:boolean" minOccurs="0" default="true" /> </xs:sequence> </xs:complexType> ...... </xs:schema>
'symmetric-binding' element 보안 설정
symmetric-binding element의 보안 설정은 웹 서비스 보안(WS-Security) 명세를 이용하여 대칭 바인딩(Symmetric Binding)으로 메시지를 보호할 때 설정한다.
대칭 바인딩(Symmetric Binding)이란, 메시지를 암호화하거나 복호화할 때 사용되는 대칭키(symmetric key)는 SOAP 메시지의 헤더 부분에 추가적인 element(EncryptedKey) 하위에 암호화된 상태로 메시지와 함께 전송되는데, 이 대칭키를 암호화하거나 복호화할 때 사용되는 토큰이 같다는 것을 의미한다. 서명할 때도 서명을 검증할 때와 같은 토큰을 통하여 이루어진다는 것을 의미한다.
하위의 'protection-token' element는 추가적으로 메시지 암호화 및 서명에 사용되는 토큰이 동일함을 의미한다.
[예 16.7] << jeus-webservices-config.xsd >>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <xs:schema xmlns="http://www.tmaxsoft.com/xml/ns/jeus" targetNamespace="http://www.tmaxsoft.com/xml/ns/jeus" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified" version="6.0"> ...... <xs:complexType name="symmetricBindingType"> <xs:sequence> <xs:element name="protection-token" type="tokenType" /> <xs:element name="algorithm-suite" type="algorithmSuiteType" minOccurs="0" default="Basic128" /> <xs:element name="layout" type="layoutType" minOccurs="0" default="Lax" /> <xs:element name="timestamp" type="xs:boolean" minOccurs="0" default="true" /> <xs:element name="encrypt-signature" type="xs:boolean" minOccurs="0" default="false" /> <xs:element name="encrypt-before-siging" type="xs:boolean" minOccurs="0" default="false" /> </xs:sequence> </xs:complexType> ...... </xs:schema>
'asymmetric-binding' element 보안 설정
asymmetric-binding element의 보안 설정은 웹 서비스 보안(WS-Security) 명세를 이용하여 비대칭 바인딩(Asymmetric Binding)으로 메시지를 보호할 때 설정한다.
비대칭 바인딩(Asymmetric Binding)이란, 메시지를 암호화하거나 복호화하는 데 사용되는 대칭 키(symmetric key)는 SOAP 메시지의 헤더 부분에 추가적인 element(EncryptedKey) 하위에 암호화된 상태로 메시지와 함께 전송되는데, 이 대칭 키를 암호화하거나 복호화할 때 사용되는 토큰이 서로 다르다는 것을 의미한다. 서명을 할 때와 서명을 검증할 때 다른 토큰을 통하여 이루어진다는 것을 의미한다.
추가적으로 하위의 'initiator-token' element와 'recipient-token' element가 있다. 각각의 설명은 다음과 같다.
구분 | 설명 |
---|---|
initiator-token | 클라이언트가 메시지를 서명할 때 사용하는 토큰이자 서버로부터 받은 암호화된 메시지를 복호화할 때 사용하는 토큰임을 의미한다. 서버가 메시지를 암호화할 때 사용하는 토큰이자 클라이언트로부터 받은 메시지의 서명을 검증할 때 사용하는 토큰임을 의미한다. |
recipient-token | 서버가 메시지를 서명할 때 사용하는 토큰이자 클라이언트로부터 받은 암호화된 메시지를 복호화할 때 사용하는 토큰임을 의미한다. 클라이언트가 메시지를 암호화할 때 사용하는 토큰이자 서버로부터 받은 메시지의 서명을 검증할 때 사용하는 토큰임을 의미한다. |
[예 16.8] << jeus-webservices-config.xsd >>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <xs:schema xmlns="http://www.tmaxsoft.com/xml/ns/jeus" targetNamespace="http://www.tmaxsoft.com/xml/ns/jeus" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified" version="6.0"> ...... <xs:complexType name="asymmetricBindingType"> <xs:sequence> <xs:element name="initiator-token" type="tokenType" /> <xs:element name="recipient-token" type="tokenType" /> <xs:element name="algorithm-suite" type="algorithmSuiteType" minOccurs="0" default="Basic128" /> <xs:element name="layout" type="layoutType" minOccurs="0" default="Strict" /> <xs:element name="timestamp" type="xs:boolean" minOccurs="0" default="true" /> <xs:element name="encrypt-before-siging" type="xs:boolean" minOccurs="0" default="false" /> </xs:sequence> </xs:complexType> ...... </xs:schema>
다음과 같이 token element 보안 설정은 'supporting-token', 'signed-supporting-token', 'endorsing-supporting-token', 'signed-endorsing-supporting-token' 중 하나를 선택할 수 있다.
구분 | 설명 |
---|---|
supporting-token | 이곳에 설정한 토큰 값은 실제 메시지의 헤더 부분에 포함되며 다른 메시지 부분을 암호화하거나 서명할 때 이용할 수 있다. |
signed-supporting-token | 'supporting-token'과 같다. 추가적으로 이 토큰 또한 서명이 된다. |
endorsing-supporting-token | 서명을 다시 서명하는 데 사용되는 토큰을 설정할 때 사용한다. 'Signature' element를 통채로 서명한다. |
signed-endorsing-supporting-token | 'endorsing-supporting-token'과 같다. 추가적으로 이 토큰 또한 원래 서명을 통해 서명한다. 상호 서명하는 것을 의미한다. |
[예 16.9] << jeus-webservices-config.xsd >>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <xs:schema xmlns="http://www.tmaxsoft.com/xml/ns/jeus" targetNamespace="http://www.tmaxsoft.com/xml/ns/jeus" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified" version="6.0"> ...... <xs:complexType name="supportingTokenType"> <xs:choice> <xs:element name="supporting-token" type="tokenType" /> <xs:element name="signed-supporting-token" type="tokenType" /> <xs:element name="endorsing-supporting-token" type="tokenType" /> <xs:element name="signed-endorsing-supporting-token" type="tokenType" /> </xs:choice> </xs:complexType> ...... </xs:schema>
다음과 같이 protection element 보안 설정은 'signed-part', 'signed-element', 'encrypted-part', 'encrypted-element', 'required-element' 중 하나를 선택할 수 있다.
구분 | 설명 |
---|---|
signed-part | 서명(검증)할 부분을 설정할 때 사용한다. |
encrypted-part | 암호화 또는 복호화할 부분을 설정할 때 사용한다. |
signed-element | 암호화 또는 복호화할 부분을 설정할 때 사용한다. 특정 element를 부분 서명할 때 사용하면 유용하다. 'signed-element' element 설정하는 경우 'disable-streaming-security' element의 값을 'true'로 함께 설정하여야 한다. 자세한 사항은 샘플을 참조한다. |
encrypted-element | 암호화 또는 복호화할 부분을 설정할 때 사용한다. 특정 element를 부분 암호화할 때 사용하면 유용하다. 'encrypted-element' element를 설정하는 경우 'disable-streaming-security' element의 값을 'true'로 함께 설정해야 한다. 자세한 사항은 샘플을 참조한다. |
[예 16.10] << jeus-webservices-config.xsd >>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <xs:schema xmlns="http://www.tmaxsoft.com/xml/ns/jeus" targetNamespace="http://www.tmaxsoft.com/xml/ns/jeus" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified" version="6.0"> ...... <xs:complexType name="protectionType"> <xs:sequence> <xs:element name="signed-part" type="protectionPartType" minOccurs="0" /> <xs:element name="encrypted-part" type="protectionPartType" minOccurs="0" /> <xs:element name="signed-element" type="xs:string" minOccurs="0" /> <xs:element name="encrypted-element" type="xs:string" minOccurs="0"> </xs:sequence> </xs:complexType> ...... </xs:schema>
'operation-policy-subject' element의 보안 설정
서비스 구현 클래스의 메소드 단위로 보안 설정을 할 수 있다. 서명 및 암호화, 이를 뒷받침하는 보안 토큰들을 추가로 설정할 수 있다.
'operation-policy-subject' element 보안 설정은 서비스 구현 클래스의 메소드 단위의 보안 설정으로 다음과 같이 크게 2가지로 나뉠 수 있다.
구분 | 설명 |
---|---|
supporting-token | 이 설정의 내용은 token과 같다. 단, 이 설정은 이 메소드에만 설정되는 값이다. |
protection | 이 설정의 내용은 protection과 같다. 단, 이 설정은 이 메소드에만 설정되는 값이다. |
[예 16.11] << jeus-webservices-config.xsd >>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <xs:schema xmlns="http://www.tmaxsoft.com/xml/ns/jeus" targetNamespace="http://www.tmaxsoft.com/xml/ns/jeus" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified" version="6.0"> ...... <xs:complexType name="operationSecurityPolicyType"> <xs:sequence> <xs:element name="supporting-token" type="supportingTokenType" minOccurs="0" /> <xs:element name="protection" type="protectionType" minOccurs="0" /> </xs:sequence> </xs:complexType> ...... </xs:schema>
'input(output)-message-policy-subject' element의 보안 설정
서비스 구현 클래스 메소드의 매개 변수 및 반환값 단위로 보안 설정을 한다. 서명 및 암호화와 이를 뒷받침하는 보안 토큰들을 추가로 설정할 수 있다.
'input(output)-message-policy-subject' element 보안 설정은 서비스 구현 클래스 메소드의 매개변수 및 반환값 단위 보안 설정으로 다음과 같이 크게 2가지로 나뉠 수 있다.
구분 | 설명 |
---|---|
supporting-token | 이 설정의 내용은 token과 같다. 단, 이 설정은 이 메소드의 매개 변수 및 반환값에만 설정되는 값이다. |
protection | 이 설정의 내용은 protection과 같다. 단, 이 설정은 이 메소드의 매개 변수 및 반환값에만 설정되는 값이다. |
[예 16.12] << jeus-webservices-config.xsd >>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <xs:schema xmlns="http://www.tmaxsoft.com/xml/ns/jeus" targetNamespace="http://www.tmaxsoft.com/xml/ns/jeus" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified" version="6.0"> ...... <xs:complexType name="messageSecurityPolicyType"> <xs:sequence> <xs:element name="supporting-token" type="supportingTokenType" minOccurs="0" /> <xs:element name="protection" type="protectionType" minOccurs="0" /> </xs:sequence> </xs:complexType> ...... </xs:schema>
WSDL로부터 구현하기 위해서는 WSDL 문서에 직접 메시지 보안 정책 설정을 하고 wsimport 콘솔 툴을 이용하여 웹 서비스를 구성한다. WSDL로부터 구현하기 위해서는 WS-Policy의 하부 스펙인 WS-SecurityPolicy의 내용을 정확하게 이해하여 WSDL에 적용하면 간단히 웹 서비스 메시지 보안을 구현할 수 있다.
WS-SecurityPolicy의 내용은 "http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/ws-securitypolicy-1.2-spec-os.html"에서 확인한다.
다음은 메시지 보안이 설정된 웹 서비스를 구현하기 위한 하나의 WSDL 예이다.
키스토어에 대한 설정은 절대 경로 혹은 상대 경로를 포함한 실제 키스토어 파일의 위치를 지정한다. 상대 경로로 지정할 때는 서비스 구현 클래스가 포함된 classes 디렉터리 하위의 META-INF 디렉터리에 키스토어 파일이 위치해야 한다.
[예 16.13] << jeus-webservices-config.xsd >>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <definitions ... targetNamespace="http://tmax.com/" name="NewWebServiceService"> <ns1:Policy xmlns:ns1="http://schemas.xmlsoap.org/ws/2004/09/policy" wsu:Id="NewWebServicePortBindingPolicy"> <ns1:ExactlyOne> <ns1:All> <ns7:SymmetricBinding xmlns:ns7="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <ns1:Policy> <ns1:ExactlyOne> <ns1:All> <ns7:AlgorithmSuite> <ns1:Policy> <ns1:ExactlyOne> <ns1:All> <ns7:TripleDes /> </ns1:All> </ns1:ExactlyOne> </ns1:Policy> </ns7:AlgorithmSuite> <ns7:IncludeTimestamp /> <ns7:Layout> <ns1:Policy> <ns1:ExactlyOne> <ns1:All> <ns7:Strict /> </ns1:All> </ns1:ExactlyOne> </ns1:Policy> </ns7:Layout> <ns7:OnlySignEntireHeadersAndBody /> <ns7:ProtectionToken> <ns1:Policy> <ns1:ExactlyOne> <ns1:All> <ns7:X509Tokenns7:IncludeToken= "http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/Never"> <ns1:Policy> <ns1:ExactlyOne> <ns1:All> <ns7:WssX509V3Token10/> </ns1:All> </ns1:ExactlyOne> </ns1:Policy> </ns7:X509Token> </ns1:All> </ns1:ExactlyOne> </ns1:Policy> </ns7:ProtectionToken> </ns1:All> </ns1:ExactlyOne> </ns1:Policy> </ns7:SymmetricBinding> <ns8:Wss11 xmlns:ns8="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <ns1:Policy> <ns1:ExactlyOne> <ns1:All> <ns8:MustSupportRefEncryptedKey /> <ns8:MustSupportRefIssuerSerial /> <ns8:MustSupportRefThumbprint /> </ns1:All> </ns1:ExactlyOne> </ns1:Policy> </ns8:Wss11> <sc:KeyStore wspp:visibility="private" alias="xws-security-server" storepass="changeit" type="JKS" location="keystore.jks" /> <sc:TrustStore wspp:visibility="private" peeralias="xws-security-client" storepass="changeit" type="JKS" location="cacerts.jks" /> <sc:ValidatorConfiguration xmlns:sc="http://schemas.sun.com/2006/03/wss/server"> <sc:Validator name="usernameValidator" classname="com.tmax.UsernamePasswordValidator" /> </sc:ValidatorConfiguration> <ns9:UsingAddressing xmlns:ns9="http://www.w3.org/2006/05/addressing/wsdl" /> </ns1:All> </ns1:ExactlyOne> </ns1:Policy> <ns10:Policy xmlns:ns10="http://schemas.xmlsoap.org/ws/2004/09/policy" wsu:Id="NewWebServicePortBinding_add_Input_Policy"> <ns10:ExactlyOne> <ns10:All> <ns11:EncryptedParts xmlns:ns11="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <ns11:Body /> </ns11:EncryptedParts> <ns12:SignedParts xmlns:ns12="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <ns12:Body /> <ns12:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing" /> <ns12:Header Namespace="http://www.w3.org/2005/08/addressing" Name="To" /> <ns12:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing" /> <ns12:Header Name="MessageId" Namespace="http://www.w3.org/2005/08/addressing" /> <ns12:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing" /> <ns12:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing" /> <ns12:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing" /> </ns12:SignedParts> <ns13:SignedSupportingTokens xmlns:ns13="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <ns10:Policy> <ns10:ExactlyOne> <ns10:All> <ns13:UsernameToken ns13:IncludeToken= "http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/ IncludeToken/AlwaysToRecipient"> <ns10:Policy> <ns10:ExactlyOne> <ns10:All> <ns13:WssUsernameToken10/> </ns10:All> </ns10:ExactlyOne> </ns10:Policy> </ns13:UsernameToken> </ns10:All> </ns10:ExactlyOne> </ns10:Policy> </ns13:SignedSupportingTokens> </ns10:All> </ns10:ExactlyOne> </ns10:Policy> <ns14:Policy xmlns:ns14="http://schemas.xmlsoap.org/ws/2004/09/policy" wsu:Id="NewWebServicePortBinding_add_Output_Policy"> <ns14:ExactlyOne> <ns14:All> <ns15:EncryptedParts xmlns:ns15="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <ns15:Body /> </ns15:EncryptedParts> <ns16:SignedParts xmlns:ns16="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <ns16:Body /> <ns16:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing" /> <ns16:Header Namespace="http://www.w3.org/2005/08/addressing" Name="To" /> <ns16:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing" /> <ns16:Header Name="MessageId" Namespace="http://www.w3.org/2005/08/addressing" /> <ns16:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing" /> <ns16:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing" /> <ns16:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing" /> </ns16:SignedParts> </ns14:All> </ns14:ExactlyOne> </ns14:Policy> <types> ... </types> <message name="add"> ... </message> <portType name="NewWebService"> ... </portType> <binding name="NewWebServicePortBinding" type="tns:NewWebService"> <ns17:PolicyReference xmlns:ns17="http://schemas.xmlsoap.org/ws/2004/09/policy" URI="#NewWebServicePortBindingPolicy" /> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" /> <operation name="add"> <soap:operation soapAction="" /> <input> <ns18:PolicyReference xmlns:ns18="http://schemas.xmlsoap.org/ws/2004/09/policy" URI="#NewWebServicePortBinding_add_Input_Policy" /> <soap:body use="literal" /> </input> <output> <ns19:PolicyReference xmlns:ns19="http://schemas.xmlsoap.org/ws/2004/09/policy" URI="#NewWebServicePortBinding_add_Output_Policy" /> <soap:body use="literal" /> </output> </operation> </binding> <service name="NewWebServiceService"> <port name="NewWebServicePort" binding="tns:NewWebServicePortBinding"> <soap:address location="http://localhost:8088/usernameAuthentication_war/NewWebServiceService" /> </port> </service> </definitions>
메시지 보안이 설정된 웹 서비스의 클라이언트는 wsit-client.xml 파일을 통해 다음과 같이 부가적으로 키스토어 및 콜백 핸들러 등을 설정해야 한다. 그 밖의 다른 메시지 보안 설정은 서버 측의 WSDL에 설정된 메시지 보안 정책을 런타임에 해석하여 메시지 보안 환경을 자동으로 구성한다.
키스토어에 대한 설정은 절대 경로 혹은 상대 경로를 포함한 실제 키스토어 파일의 위치를 지정한다. 상대 경로로 지정할 때는 서비스 구현 클래스가 포함된 classes 디렉터리 하위의 META-INF 디렉터리에 키스토어 파일이 위치해야 한다.
[예 16.14] << jeus-webservices-config.xsd >>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <definitions xmlns="http://schemas.xmlsoap.org/wsdl/" ... targetNamespace="http://server.fromjava/"> <wsp:UsingPolicy /> <wsp:Policy wsu:Id="TmaxBP0"> <wsp:ExactlyOne> <wsp:All> <CallbackHandlerConfiguration xmlns="http://schemas.sun.com/2006/03/wss/client"> <CallbackHandler default="user_jeus" name="usernameHandler" /> <CallbackHandler default="password_jeus" name="passwordHandler" /> </CallbackHandlerConfiguration> <TrustStore location="cacerts.jks" peeralias="xws-security-server" storepass="changeit" type="JKS" xmlns:ns0="http://java.sun.com/xml/ns/wsit/policy" ns0:visibility="private" xmlns="http://schemas.sun.com/2006/03/wss/client" /> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> <types> ... </types> <message name="addNumbers"> ... </message> <portType name="AddNumbersImpl"> ... </portType> <binding name="AddNumbersImplPortBinding" type="tns:AddNumbersImpl"> <wsp:PolicyReference URI="#TmaxBP0" /> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> <operation name="addNumbers"> <soap:operation soapAction="" /> <input> <soap:body use="literal" /> </input> <output> <soap:body use="literal" /> </output> </operation> </binding> <service name="AddNumbersImplService"> <port binding="tns:AddNumbersImplPortBinding" name="AddNumbersImplPort"> <soap:address location="http://localhost:8088/DocLitEchoService/AddNumbersImplService" /> </port> </service> </definitions>
서버 웹 서비스의 설정은 service-config.xml 파일을 작성하고 사용자명의 유효자(Validator) 클래스를 작성한다.
[예 16.15] <<service-config.xml>>
<?xml version="1.0" encoding="UTF-8"?> <web-services-config xmlns="http://www.tmaxsoft.com/xml/ns/jeus"> <policy> <endpoint-policy-subject> <security-policy> <security-binding> <symmetric-binding> <protection-token> <x509-token> <include-token>true</include-token> </x509-token> </protection-token> </symmetric-binding> </security-binding> <token> <signed-supporting-token> <username-token> <username-password-validator> fromjava.server.UsernamePasswordValidator </username-password-validator> <include-token>true</include-token> </username-token> </signed-supporting-token> </token> <protection> <signed-part>...</signed-part> <encrypted-part>...</encrypted-part> </protection> <wss-version>11</wss-version> <keystore>...</keystore> </security-policy> </endpoint-policy-subject> </policy> </web-services-config>
com.sun.xml.wss.impl.callback.PasswordValidationCallback.PasswordValidator을 구현하여 username token을 사용해서 접근한 사용자의 username과 password를 validate한다.
[예 16.16] << UsernamePasswordValidator.java >>
public class UsernamePasswordValidator implements PasswordValidationCallback.PasswordValidator { public boolean validate(PasswordValidationCallback.Request request) throws PasswordValidationCallback.PasswordValidationException { ... return false; } private boolean validateUserFromDB(String username, String password) { ... return false; } }
클라이언트 웹 서비스의 설정은 추가적으로 wsit-client.xml에 키스토어(Truststore) 설정과 함께 사용자명 핸들러(Handler)의 설정을 해야 한다.
wsit-client.xml 파일에 다음과 같이 설정한다.
[예 16.17] <<wsit-client.xml>>
<?xml version="1.0" encoding="UTF-8"?> <definitions xmlns="http://schemas.xmlsoap.org/wsdl/" ... targetNamespace="http://server.fromjava/"> <wsp:UsingPolicy /> <wsp:Policy wsu:Id="TmaxBP0"> <wsp:ExactlyOne> <wsp:All> <CallbackHandlerConfiguration xmlns="http://schemas.sun.com/2006/03/wss/client"> <CallbackHandler default="user_jeus" name="usernameHandler" /> <CallbackHandler default="password_jeus" name="passwordHandler" /> </CallbackHandlerConfiguration> <TrustStore location="cacerts.jks" peeralias="xws-security-server" storepass="changeit" type="JKS" xmlns:ns0="http://java.sun.com/xml/ns/wsit/policy" ns0:visibility="private" xmlns="http://schemas.sun.com/2006/03/wss/client" /> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> ... <binding name="AddNumbersImplPortBinding" type="tns:AddNumbersImpl"> <wsp:PolicyReference URI="#TmaxBP0" /> ... </binding> ... </definitions>
javax.security.auth.callback.CallbackHandler을 구현하여 각각의 callback을 CallbackHandler에 전달함으로써 여러 가지 설정을 해 줄 수 있다. 전달받은 callback의 종류에 맞추어 정책에 따른 설정을 한다.
위 예제에서는 NameCallback과 PasswordCallback을 전달받아 callback에 username과 password를 설정하는 callbackHandler를 다음과 같이 구성한다. 다음의 예제에서는 클래스 파일 내에서 username과 password를 미리 입력 해 놓았지만 경우에 따라서 다양한 reader객체를 사용하여 사용자로부터 직접 입력받을 수도 있다.
[예 16.18] << UsernamePasswordCallbackHandler.java >>
public class UsernamePasswordCallbackHandler implements CallbackHandler { public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (int i = 0; i < callbacks.length; i++) { Callback callback = callbacks[i]; if (callback instanceof NameCallback) { ((NameCallback) callback).setName("user_jeus"); } else if (callback instanceof PasswordCallback) { ((PasswordCallback) callback).setPassword((new String( "password_jeus")).toCharArray()); } else { throw new UnsupportedCallbackException(callback, "Unknow callback for username or password"); } } } }
서버 측 웹 서비스의 설정은 service-config.xml 웹 서비스 설정 파일로 구성할 수 있다.
service-config.xml 웹 서비스 설정 파일에 다음과 같이 설정한다.
[예 16.19] << service-config.xml >>
<?xml version="1.0" encoding="UTF-8"?> <web-services-config xmlns="http://www.tmaxsoft.com/xml/ns/jeus"> <policy> <endpoint-policy-subject> <security-policy> <security-binding> <asymmetric-binding> <initiator-token> <x509-token> <include-token>true</include-token> </x509-token> </initiator-token> <recipient-token> <x509-token> <include-token>false</include-token> </x509-token> </recipient-token> </asymmetric-binding> </security-binding> <protection> <signed-part>...</signed-part> <encrypted-part>...</encrypted-part> </protection> <keystore>...</keystore> <truststore>...</truststore> </security-policy> </endpoint-policy-subject> </policy> </web-services-config>
클라이언트 측 웹 서비스의 설정은 추가적으로 wsit-client.xml에 키스토어(Keystore, Truststore) 설정을 해야 한다.
wsit-client.xml 파일에 다음과 같이 설정한다.
[예 16.20] << wsit-client.xml >>
<?xml version="1.0" encoding="UTF-8"?> <definitions xmlns="http://schemas.xmlsoap.org/wsdl/" ... targetNamespace="http://server.fromjava/"> <wsp:UsingPolicy/> <wsp:Policy wsu:Id="TmaxBP0"> <wsp:ExactlyOne> <wsp:All> <KeyStore alias="xws-security-client" location="keystore.jks" storepass="changeit" type="JKS" xmlns:ns0="http://java.sun.com/xml/ns/wsit/policy" ns0:visibility="private" xmlns="http://schemas.sun.com/2006/03/wss/client"/> <TrustStore location="cacerts.jks" peeralias="xws-security-server" storepass="changeit" type="JKS" xmlns:ns0="http://java.sun.com/xml/ns/wsit/policy" ns0:visibility="private" xmlns="http://schemas.sun.com/2006/03/wss/client"/> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> ... <binding name="AddNumbersImplPortBinding" type="tns:AddNumbersImpl"> <wsp:PolicyReference URI="#TmaxBP0"/> ... </binding> ... </definitions>
서버측 웹 서비스의 설정은 service-config.xml 웹 서비스 설정 파일로 구성할 수 있다.
service-config.xml 웹 서비스 설정 파일에 다음과 같이 설정한다.
[예 16.21] << service-config.xml >>
<?xml version="1.0" encoding="UTF-8"?> <web-services-config xmlns="http://www.tmaxsoft.com/xml/ns/jeus"> <policy> <endpoint-policy-subject> <security-policy> <security-binding> <transport-binding> <transport-token> <https-token/> </transport-token> </transport-binding> </security-binding> </security-policy> <operation-policy-subject> <operation-java-name>addNumbers</operation-java-name> <input-message-policy-subject> <security-policy> <supporting-token> <signed-supporting-token> <saml-token> </saml-token> </signed-supporting-token> </supporting-token> </security-policy> </input-message-policy-subject> </operation-policy-subject> </endpoint-policy-subject> </policy> </web-services-config>
클라이언트 측 웹 서비스의 설정은 추가적으로 wsit-client.xml에 SAML 메시지의 핸들러(Handler) 클래스 설정을 해야 한다.
wsit-client.xml 파일에 다음과 같이 설정한다.
[예 16.22] << wsit-client.xml >>
<?xml version="1.0" encoding="UTF-8"?> <definitions xmlns="http://schemas.xmlsoap.org/wsdl/" ... targetNamespace="http://server.fromjava/"> <ns5:Policy xmlns:ns5="http://schemas.xmlsoap.org/ws/2004/09/policy" wsu:Id="TmaxBO1TmaxIn1"> <ns5:ExactlyOne> <ns5:All> <CallbackHandlerConfiguration xmlns="http://schemas.sun.com/2006/03/wss/client"> <CallbackHandler classname="xwss.saml.SamlCallbackHandler" name="samlHandler" /> </CallbackHandlerConfiguration> </ns5:All> </ns5:ExactlyOne> </ns5:Policy> ... <binding name="AddNumbersImplPortBinding" type="tns:AddNumbersImpl"> ... <operation name="addNumbers"> <soap:operation soapAction="" /> <input> <ns10:PolicyReference xmlns:ns10="http://schemas.xmlsoap.org/ws/2004/09/policy" URI="#TmaxBO1TmaxIn1" /> <soap:body use="literal" /> </input> <output> <soap:body use="literal" /> </output> </operation> </binding> ... </definitions>
SAML 표준에 따라 SOAP 요청 메시지에 정보를 담기 위해 예제에서는 javax.security.auth.callback.CallbackHandler를 구현하는 SamlCallbackHandler를 사용한다. SamlCallbackHandler에서는 callback의 종류에 따라 필요한 assertion을 저장하는 역할을 한다. 다음은 이 예제에서 사용되는 SamlCallbackHandler의 모습이다.
[예 16.23] << SamlCallbackHandler.java >>
public class SamlCallbackHandler implements CallbackHandler { ... public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (int i = 0; i < callbacks.length; i++) { if (callbacks[i] instanceof SAMLCallback) { try { SAMLCallback samlCallback = (SAMLCallback) callbacks[i]; if (samlCallback.getConfirmationMethod().equals( samlCallback.SV_ASSERTION_TYPE)) { samlCallback.setAssertionElement(createSVSAMLAssertion()); svAssertion = samlCallback.getAssertionElement(); } else if (samlCallback.getConfirmationMethod().equals( samlCallback.HOK_ASSERTION_TYPE)) { samlCallback.setAssertionElement(createHOKSAMLAssertion()); hokAssertion = samlCallback.getAssertionElement(); } else { throw new Exception( "SAML Assertion Type is not matched."); } } catch (Exception ex) { ex.printStackTrace(); } } else { throw unsupported; } } } private static Element createSVSAMLAssertion() {...} private static Element createSVSAMLAssertion20() {...} private Element createHOKSAMLAssertion() {...} private Element createHOKSAMLAssertion20() {...} ... }
웹 서비스의 서버 설정은 service-config.xml 웹 서비스 설정 파일로 구성할 수 있다.
service-config.xml 웹 서비스 설정 파일에 다음과 같이 설정한다.
[예 16.24] <<service-config.xml>>
<?xml version="1.0" encoding="UTF-8"?> <web-services-config xmlns="http://www.tmaxsoft.com/xml/ns/jeus"> <policy> <endpoint-policy-subject> <portcomponent-wsdl-name>AddNumbersPort</portcomponent-wsdl-name> <addressing-policy> <www-w3-org /> </addressing-policy> <security-policy> <security-binding> <symmetric-binding> <protection-token> <secure-conversation-token> <asymmetric-binding-initiator-token> <include-token>true</include-token> </asymmetric-binding-initiator-token> <asymmetric-binding-recipient-token> </asymmetric-binding-recipient-token> <include-token>true</include-token> </secure-conversation-token> </protection-token> <encrypt-signature>true</encrypt-signature> </symmetric-binding> </security-binding> <trust>true</trust> <keystore>...</keystore> <truststore>...</truststore> </security-policy> <operation-policy-subject> <operation-wsdl-name>addNumbers</operation-wsdl-name> <input-message-policy-subject> <security-policy> <protection> <signed-part>...</signed-part> <encrypted-part>...</encrypted-part> </protection> </security-policy> </input-message-policy-subject> </operation-policy-subject> </endpoint-policy-subject> </policy> </web-services-config>
클라이언트측 웹 서비스의 설정은 추가적으로 wsit-client.xml에 키스토어(Keystore, Truststore) 설정을 해야 한다.
wsit-client.xml 파일에 다음과 같이 설정한다.
[예 16.25] <<wsit-client.xml>>
<?xml version="1.0" encoding="UTF-8"?> <definitions xmlns="http://schemas.xmlsoap.org/wsdl/" ... xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"> <message name="add" /> <message name="addResponse" /> <portType name="NewWebService"> <wsdl:operation name="add"> <wsdl:input message="tns:add" /> <wsdl:output message="tns:addResponse" /> </wsdl:operation> </portType> <binding name="NewWebServicePortBinding" type="tns:NewWebService"> <wsp:PolicyReference URI="#NewWebServicePortBindingPolicy" /> <soap12:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> <wsdl:operation name="add"> <soap12:operation soapAction="http://xmlsoap.org/Ping" style="document" /> <wsdl:input> <soap12:body use="literal" /> </wsdl:input> <wsdl:output> <soap12:body use="literal" /> </wsdl:output> </wsdl:operation> </binding> <service name="NewWebServiceService"> <wsdl:port name="NewWebServicePort" binding="tns:NewWebServicePortBinding"> <soap12:address location="REPLACE_WITH_ACTUAL_ADDRESS" /> </wsdl:port> </service> <wsp:Policy wsu:Id="NewWebServicePortBindingPolicy" xmlns:scc="http://schemas.sun.com/ws/2006/05/sc/client"> <wsp:ExactlyOne> <wsp:All> <sc:KeyStore wspp:visibility="private" location="./keystore.jks" type="JKS" alias="xws-security-client" storepass="changeit"> </sc:KeyStore> <sc:TrustStore wspp:visibility="private" location="./cacerts.jks" type="JKS" storepass="changeit" peeralias="xws-security-server" stsalias="wssip"> </sc:TrustStore> <scc:SCClientConfiguration wspp:visibility="private"> <scc:LifeTime>36000</scc:LifeTime> </scc:SCClientConfiguration> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> </definitions>
웹 서비스의 서버 설정은 service-config.xml 웹 서비스 설정 파일로 구성할 수 있다.
service-config.xml 웹 서비스 설정 파일에 다음과 같이 설정한다.
[예 16.26] <<service-config.xml>>
<?xml version="1.0" encoding="UTF-8"?> <web-services-config xmlns="http://www.tmaxsoft.com/xml/ns/jeus"> <policy> <endpoint-policy-subject> <!-- 웹 서비스 신뢰는 WS-Addressing 프레임워크 위에서 동작한다 --> <addressing-policy> <www-w3-org /> </addressing-policy> <security-policy> <!-- 웹 서비스는 x509 토큰을 보안 토큰으로 사용할 것을 명시한다 --> <security-binding> <symmetric-binding> <protection-token> <x509-token /> </protection-token> <layout>Strict</layout> </symmetric-binding> </security-binding> <!-- 웹 서비스는 추가적으로 다음 주소의 STS로부터 보안 토큰을 발급 받을 것을 명시한다 --> <token> <endorsing-supporting-token> <issued-token> <issuer-address> http://localhost:8088/trust_sts/SecurityTokenService </issuer-address> </issued-token> </endorsing-supporting-token> </token> <wss-version>11</wss-version> <trust>true</trust> ... </security-policy> ... </endpoint-policy-subject> </policy> </web-services-config>
다음과 같은 WS-SecurityPolicy 설정을 WSDL의 WS-Policy 프레임워크을 통해 설정한다.
[예 16.27] WS-SecurityPolicy 설정 : <<sts.wsdl>>
<?xml version="1.0" encoding="UTF-8"?> <wsdl:definitions ...> <wsp:Policy wsu:Id="TmaxSTSServerPolicy"> <wsp:ExactlyOne> <wsp:All> <sp:SymmetricBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <wsp:Policy> <sp:ProtectionToken> <wsp:Policy> <sp:X509Token sp:IncludeToken= "http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/Never"> <wsp:Policy> <sp:RequireDerivedKeys /> <sp:RequireThumbprintReference /> <sp:WssX509V3Token10 /> </wsp:Policy> </sp:X509Token> </wsp:Policy> </sp:ProtectionToken> <sp:AlgorithmSuite> <wsp:Policy> <sp:Basic128 /> </wsp:Policy> </sp:AlgorithmSuite> <sp:Layout> <wsp:Policy> <sp:Lax /> </wsp:Policy> </sp:Layout> <sp:IncludeTimestamp /> <sp:EncryptSignature /> <sp:OnlySignEntireHeadersAndBody /> </wsp:Policy> </sp:SymmetricBinding> <sp:SignedSupportingTokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <wsp:Policy> <sp:UsernameToken sp:IncludeToken= "http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken /AlwaysToRecipient"> <wsp:Policy> <sp:WssUsernameToken10 /> </wsp:Policy> </sp:UsernameToken> </wsp:Policy> </sp:SignedSupportingTokens> <sp:Wss11 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <wsp:Policy> <sp:MustSupportRefKeyIdentifier /> <sp:MustSupportRefIssuerSerial /> <sp:MustSupportRefThumbprint /> <sp:MustSupportRefEncryptedKey /> </wsp:Policy> </sp:Wss11> <sp:Trust10 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <wsp:Policy> <sp:MustSupportIssuedTokens /> <sp:RequireClientEntropy /> <sp:RequireServerEntropy /> </wsp:Policy> </sp:Trust10> ... <sc:ValidatorConfiguration xmlns:sc="http://schemas.sun.com/2006/03/wss/server"> <sc:Validator name="usernameValidator" classname="trust.sts.UsernamePasswordValidator" /> </sc:ValidatorConfiguration> <tc:STSConfiguration xmlns:tc="http://schemas.sun.com/ws/2006/05/trust/server" encryptIssuedKey="true" encryptIssuedToken="false"> <tc:LifeTime>36000</tc:LifeTime> <tc:Contract> com.sun.xml.ws.security.trust.impl.IssueSamlTokenContractImpl </tc:Contract> <tc:Issuer>TmaxsoftSTS</tc:Issuer> <tc:ServiceProviders> <tc:ServiceProvider endPoint="http://localhost:8088/trust_server/FinancialService"> <tc:CertAlias>bob</tc:CertAlias> <tc:TokenType> http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1 </tc:TokenType> </tc:ServiceProvider> <tc:ServiceProvider endPoint="default"> <tc:CertAlias>bob</tc:CertAlias> <tc:TokenType> http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1 </tc:TokenType> </tc:ServiceProvider> </tc:ServiceProviders> </tc:STSConfiguration> <wsap10:UsingAddressing /> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> ... <wsdl:binding name="ISecurityTokenService_Binding" type="tns:ISecurityTokenService"> <wsp:PolicyReference URI="#TmaxSTSServerPolicy" /> ... </wsdl:binding> ... </wsdl:definitions>
클라이언트 측 웹 서비스의 설정은 wsit-client.xml에 서버, STS 각각을 위한 키스토어(Keystore, Truststore) 설정을 해야 한다.
wsit-client.xml 파일에 다음과 같이 설정한다.
[예 16.28] <<wsit-client.xml>>
<?xml version="1.0" encoding="UTF-8"?> <wsdl:definitions targetNamespace="http://tempuri.org/" ...> <!-- FinancialService WSDL --> <wsp:Policy wsu:Id="TmaxFSClientPolicy" ...> <wsp:ExactlyOne> <wsp:All> <sc:KeyStore ... /> <sc:TrustStore ... /> <scc:SCClientConfiguration wspp:visibility="private"> <scc:LifeTime>36000</scc:LifeTime> </scc:SCClientConfiguration> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> ... <wsdl:binding name="IFinancialService_Binding" type="tns:IFinancialService"> <wsp:PolicyReference URI="#TmaxFSClientPolicy" /> ... </wsdl:binding> <wsdl:service name="FinancialService"> <wsdl:port name="IFinancialService_Port" binding="tns:IFinancialService_Binding"> <soap:address location="http://localhost:8088/trust_server/FinancialService" /> </wsdl:port> </wsdl:service> <!-- STSService WSDL --> <wsp:Policy wsu:Id="TmaxSTSClientPolicy" ...> <wsp:ExactlyOne> <wsp:All> <sc:KeyStore ... /> <sc:TrustStore ... /> <sc:CallbackHandlerConfiguration xmlns:sc="http://schemas.sun.com/2006/03/wss/client"> <sc:CallbackHandler default="alice" name="usernameHandler" /> <sc:CallbackHandler default="alice" name="passwordHandler" /> </sc:CallbackHandlerConfiguration> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> ... <wsdl:binding name="ISecurityTokenService_Binding" type="tns:ISecurityTokenService"> <wsp:PolicyReference URI="#TmaxSTSClientPolicy" /> ... </wsdl:binding> <wsdl:service name="SecurityTokenService"> <wsdl:port name="ISecurityTokenService_Port" binding="tns:ISecurityTokenService_Binding"> <soap:address location="http://localhost:8088/trust_sts/STSImplService" /> </wsdl:port> </wsdl:service> </wsdl:definitions>
다음은 실행 화면이다.
<<__Exception__>> com.sun.xml.ws.server.UnsupportedMediaException: Unsupported Content-Type: application/soap+xml Supported ones are: [text/xml] at com.sun.xml.ws.encoding.StreamSOAPCodec.decode(StreamSOAPCodec.java:295) at com.sun.xml.ws.encoding.StreamSOAPCodec.decode(StreamSOAPCodec.java:129) at com.sun.xml.ws.encoding.SOAPBindingCodec.decode(SOAPBindingCodec.java:287) at jeus.webservices.jaxws.transport.http.HttpAdapter.decodePacket (HttpAdapter.java:322) at jeus.webservices.jaxws.transport.http.HttpAdapter.access$3 (HttpAdapter.java:287) at jeus.webservices.jaxws.transport.http.HttpAdapter$HttpToolkit.handle (HttpAdapter.java:517) at jeus.webservices.jaxws.transport.http.HttpAdapter.handle (HttpAdapter.java:272) at jeus.webservices.jaxws.transport.http.EndpointAdapter.handle (EndpointAdapter.java:149) at jeus.webservices.jaxws.transport.http.servlet.WSServletDelegate.doGet (WSServletDelegate.java:139) at jeus.webservices.jaxws.transport.http.servlet.WSServletDelegate.doPost (WSServletDelegate.java:170) at jeus.webservices.jaxws.transport.http.servlet.WSServlet.doPost (WSServlet.java:23) at javax.servlet.http.HttpServlet.service(HttpServlet.java:725) at javax.servlet.http.HttpServlet.service(HttpServlet.java:818) at jeus.servlet.engine.ServletWrapper.executeServlet(ServletWrapper.java:328) at jeus.servlet.engine.ServletWrapper.execute(ServletWrapper.java:222) at jeus.servlet.engine.HttpRequestProcessor.run(HttpRequestProcessor.java:278) <<__!Exception__>> [2999.01.01 00:00:00][0][bxxx] [TMAX-xx] Unsupported Content-Type: application/soap+xml Supported ones are: [text/xml] <<__Exception__>> com.sun.xml.ws.server.UnsupportedMediaException: Unsupported Content-Type: application/soap+xml Supported ones are: [text/xml] at com.sun.xml.ws.encoding.StreamSOAPCodec.decode(StreamSOAPCodec.java:295) at com.sun.xml.ws.encoding.StreamSOAPCodec.decode(StreamSOAPCodec.java:129) at com.sun.xml.ws.encoding.SOAPBindingCodec.decode(SOAPBindingCodec.java:287) at jeus.webservices.jaxws.transport.http.HttpAdapter.decodePacket (HttpAdapter.java:322) at jeus.webservices.jaxws.transport.http.HttpAdapter.access$3 (HttpAdapter.java:287) at jeus.webservices.jaxws.transport.http.HttpAdapter$HttpToolkit.handle (HttpAdapter.java:517) at jeus.webservices.jaxws.transport.http.HttpAdapter.handle(HttpAdapter.java:272) at jeus.webservices.jaxws.transport.http.EndpointAdapter.handle (EndpointAdapter.java:149) at jeus.webservices.jaxws.transport.http.servlet.WSServletDelegate.doGet (WSServletDelegate.java:139) at jeus.webservices.jaxws.transport.http.servlet.WSServletDelegate.doPost (WSServletDelegate.java:170) at jeus.webservices.jaxws.transport.http.servlet.WSServlet.doPost (WSServlet.java:23) at javax.servlet.http.HttpServlet.service(HttpServlet.java:725) at javax.servlet.http.HttpServlet.service(HttpServlet.java:818) at jeus.servlet.engine.ServletWrapper.executeServlet(ServletWrapper.java:328) at jeus.servlet.engine.ServletWrapper.execute(ServletWrapper.java:222) at jeus.servlet.engine.HttpRequestProcessor.run(HttpRequestProcessor.java:278) <<__!Exception__>> user alice is a validate user. your company : Tmaxsoft your department : Infra
클라이언트를 실행하면 클라이언트가 STS의 URL 정보를 얻기 위해 여러 가지 접미 URL을 통해 연결을 시도해 본다. 여기서 로그 레벨이 'FINE' 이상인 경우 위와 같은 Exception이 발생하는 것을 볼 수 있다.
JEUS 웹 서비스의 메시지 수준 보안은 위에서 설명한대로 웹 서비스 보안 정책(Web Service Secure Policy)을 통해 동작한다. 즉, WSDL 문서 내에 직접적으로 웹 서비스 보안 정책을 설정하거나 wsit-endpoint.xml에 웹 서비스 보안 정책을 설정하는 것으로 JEUS 웹 서비스 메시지 수준 보안의 설정은 완료된다.
JEUS에서는 추가적으로 service-config.xml을 통해 웹 서비스 정책 설정 또한 지원하며 이는 웹 서비스 보안 정책을 지원한다. 따라서 사용자가 웹 서비스 정책 및 웹 서비스 정책에 대해 알지 못하더라도 서버 측과 클라이언트 측 간에 이러한 service-config.xml 파일의 공유가 가능하다면 간단히 이러한 service-config.xml 파일을 통해 양 끝단의 메시지 수준의 보안을 간단하게 처리할 수 있다. 이는 JAX-RPC (JEUS 5) 웹 서비스의 메시지 수준 보안 방식과 유사하다.
JAX-RPC (JEUS 5) 웹 서비스 메시지 수준 보안에서 암호화를 설정하는 방식은 다음과 같이 jeus-webservices-dd.xml(서버) 또는 jeus-web-dd.xml(클라이언트)을 통해 설정을 하는 것이었다.
[예 16.29] << jeus-webservices-dd.xml >>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <jeus-webservices-dd xmlns="http://www.tmaxsoft.com/xml/ns/jeus"> <service> <webservice-description-name> PingSecurityService </webservice-description-name> <port> <port-component-name>PingPort</port-component-name> <security> <request-receiver> <action-list>Encrypt</action-list> <password-callback-class> ping.PingPWCallback </password-callback-class> <decryption> <keystore> <key-type>jks</key-type> <keystore-password>changeit</keystore-password> <keystore-filename> server-keystore.jks </keystore-filename> </keystore> </decryption> </request-receiver> <response-sender> <action-list>Encrypt</action-list> <password-callback-class> ping.PingPWCallback </password-callback-class> <encryption-infos> <encryption-info> <encryptionUser>xws-security-client</encryptionUser> <keyIdentifier>DirectReference</keyIdentifier> <keystore> <key-type>jks</key-type> <keystore-password>changeit</keystore-password> <keystore-filename> server-truststore.jks </keystore-filename> </keystore> </encryption-info> </encryption-infos> </response-sender> </security> </port> </service> </jeus-webservices-dd>
이에 JAX-WS(JEUS 6) 웹 서비스의 메시지 수준 보안은 웹 서비스를 생성할 때, 즉 wsgen 혹은 wsimport 통해 웹 서비스를 생성할 때 service-config.xml 파일을 추가적으로 -policy 인자와 함께 명령문에 설정한다.
[예 16.30] << service-config.xml >>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <web-services-config xmlns="http://www.tmaxsoft.com/xml/ns/jeus"> <policy> <endpoint-policy-subject> <portcomponent-wsdl-name>PingPort</portcomponent-wsdl-name> <security-policy> <security-binding> <asymmetric-binding> <initiator-token> <x509-token/> </initiator-token> <recipient-token> <x509-token/> </recipient-token> </asymmetric-binding> </security-binding> <keystore> <keystore-file> <alias>xws-security-client</alias> <key-type>JKS</key-type> <keystore-password>changeit</keystore-password> <keystore-filename> client-keystore.jks </keystore-filename> </keystore-file> </keystore> <truststore> <keystore-file> <alias>xws-security-server</alias> <key-type>JKS</key-type> <keystore-password>changeit</keystore-password> <keystore-filename> client-truststore.jks </keystore-filename> </keystore-file> </truststore> </security-policy> <operation-policy-subject> <operation-wsdl-name>ping</operation-wsdl-name> <input-message-policy-subject> <security-policy> <protection> <encrypted-part> <body/> </encrypted-part> </protection> </security-policy> </input-message-policy-subject> <output-message-policy-subject> <security-policy> <protection> <encrypted-part> <body/> </encrypted-part> </protection> </security-policy> </output-message-policy-subject> </operation-policy-subject> </endpoint-policy-subject> </policy> </web-services-config>
JAX-RPC(JEUS 5) 웹 서비스 메시지 수준 보안에서 서명을 설정하는 방식은 다음과 같이 jeus-webservices-dd.xml(서버) 또는 jeus-web-dd.xml(클라이언트)을 통해 설정을 하는 것이었다.
[예 16.31] << jeus-webservices-dd.xml >>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <jeus-webservices-dd xmlns="http://www.tmaxsoft.com/xml/ns/jeus"> <service> <webservice-description-name> PingSecurityService </webservice-description-name> <port> <port-component-name>PingPort</port-component-name> <security> <request-receiver> <action-list>Signature</action-list> <password-callback-class> ping.PingPWCallback </password-callback-class> <signature-verification> <keystore> <key-type>jks</key-type> <keystore-password>changeit</keystore-password> <keystore-filename> server-truststore.jks </keystore-filename> </keystore> </signature-verification> </request-receiver> <response-sender> <action-list>Signature</action-list> <password-callback-class> ping.PingPWCallback </password-callback-class> <user>xws-security-server</user> <signature-infos> <signature-info> <keyIdentifier>DirectReference</keyIdentifier> <keystore> <key-type>jks</key-type> <keystore-password>changeit</keystore-password> <keystore-filename> server-keystore.jks </keystore-filename> </keystore> </signature-info> </signature-infos> </response-sender> </security> </port> </service> </jeus-webservices-dd>
이에 JAX-WS(JEUS 6) 웹 서비스의 메시지 수준 보안은 웹 서비스를 생성할 때, 즉 wsgen 혹은 wsimport 통해 웹 서비스를 생성할 때 service-config.xml 파일을 추가적으로 -policy 인자와 함께 명령문에 설정한다.
[예 16.32] << service-config.xml >>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <web-services-config xmlns="http://www.tmaxsoft.com/xml/ns/jeus"> <policy> <endpoint-policy-subject> <portcomponent-wsdl-name>PingPort</portcomponent-wsdl-name> <security-policy> <security-binding> <asymmetric-binding> <initiator-token> <x509-token/> </initiator-token> <recipient-token> <x509-token/> </recipient-token> </asymmetric-binding> </security-binding> <keystore> <keystore-file> <alias>xws-security-client</alias> <key-type>JKS</key-type> <keystore-password>changeit</keystore-password> <keystore-filename> client-keystore.jks </keystore-filename> </keystore-file> </keystore> <truststore> <keystore-file> <alias>xws-security-server</alias> <key-type>JKS</key-type> <keystore-password>changeit</keystore-password> <keystore-filename> client-truststore.jks </keystore-filename> </keystore-file> </truststore> </security-policy> <operation-policy-subject> <operation-wsdl-name>ping</operation-wsdl-name> <input-message-policy-subject> <security-policy> <protection> <signed-part> <body/> </signed-part> </protection> </security-policy> </input-message-policy-subject> <output-message-policy-subject> <security-policy> <protection> <signed-part> <body/> </signed-part> </protection> </security-policy> </output-message-policy-subject> </operation-policy-subject> </endpoint-policy-subject> </policy> </web-services-config>
JAX-RPC (JEUS 5) 웹 서비스 메시지 수준 보안에서 Timestamp을 설정하는 방식은 다음과 같이 jeus-webservices-dd.xml(서버) 또는 jeus-web-dd.xml(클라이언트)을 통해 설정을 하는 것이었다.
[예 16.33] << jeus-webservices-dd.xml >>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <jeus-webservices-dd xmlns="http://www.tmaxsoft.com/xml/ns/jeus"> <service> <webservice-description-name> PingSecurityService </webservice-description-name> <port> <port-component-name>PingPort</port-component-name> <security> <request-receiver> <action-list>Signature Timestamp</action-list> <password-callback-class> ping.PingPWCallback </password-callback-class> <signature-verification> <keystore> <key-type>jks</key-type> <keystore-password>changeit</keystore-password> <keystore-filename> server-truststore.jks </keystore-filename> </keystore> </signature-verification> </request-receiver> <response-sender> <action-list>Signature</action-list> <password-callback-class> ping.PingPWCallback </password-callback-class> <user>xws-security-server</user> <signature-infos> <signature-info> <keyIdentifier>DirectReference</keyIdentifier> <keystore> <key-type>jks</key-type> <keystore-password>changeit</keystore-password> <keystore-filename> server-keystore.jks </keystore-filename> </keystore> </signature-info> </signature-infos> </response-sender> </security> </port> </service> </jeus-webservices-dd>
이에 JAX-WS (JEUS 6) 웹 서비스의 메시지 수준 보안은 웹 서비스를 생성할 때, 즉 wsgen 혹은 wsimport 통해 웹 서비스를 생성할 때 service-config.xml 파일을 추가적으로 -policy 인자와 함께 명령문에 설정한다.
[예 16.34] << service-config.xml >>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<web-services-config xmlns="http://www.tmaxsoft.com/xml/ns/jeus">
<policy>
<endpoint-policy-subject>
<portcomponent-wsdl-name>PingPort</portcomponent-wsdl-name>
<security-policy>
<security-binding>
<asymmetric-binding>
<initiator-token>
<x509-token/>
</initiator-token>
<recipient-token>
<x509-token/>
</recipient-token>
</asymmetric-binding>
<timestamp>true</timestamp>
</security-binding>
<keystore>
<keystore-file>
<alias>xws-security-client</alias>
<key-type>JKS</key-type>
<keystore-password>changeit</keystore-password>
<keystore-filename>
client-keystore.jks
</keystore-filename>
</keystore-file>
</keystore>
<truststore>
<keystore-file>
<alias>xws-security-server</alias>
<key-type>JKS</key-type>
<keystore-password>changeit</keystore-password>
<keystore-filename>
client-truststore.jks
</keystore-filename>
</keystore-file>
</truststore>
</security-policy>
<operation-policy-subject>
<operation-wsdl-name>ping</operation-wsdl-name>
<input-message-policy-subject>
<security-policy>
<protection>
<signed-part>
<body/>
</signed-part>
</protection>
</security-policy>
</input-message-policy-subject>
<output-message-policy-subject>
<security-policy>
<protection>
<signed-part>
<body/>
</signed-part>
</protection>
</security-policy>
</output-message-policy-subject>
</operation-policy-subject>
</endpoint-policy-subject>
</policy>
</web-services-config>
JAX-RPC(JEUS 5) 웹 서비스 메시지 수준 보안에서 Timestamp을 설정하는 방식은 다음과 같이 jeus-webservices-dd.xml(서버) 또는 jeus-web-dd.xml(클라이언트)을 통해 설정을 하는 것이었다.
[예 16.35] << jeus-webservices-dd.xml >>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <jeus-webservices-dd xmlns="http://www.tmaxsoft.com/xml/ns/jeus"> <service> <webservice-description-name> PingSecurityService </webservice-description-name> <port> <port-component-name>PingPort</port-component-name> <security> <request-receiver> <action-list>Signature UsernameToken</action-list> <password-callback-class> ping.PingPWCallback </password-callback-class> <signature-verification> <keystore> <key-type>jks</key-type> <keystore-password>changeit</keystore-password> <keystore-filename> server-truststore.jks </keystore-filename> </keystore> </signature-verification> </request-receiver> <response-sender> <action-list>Signature UsernameToken</action-list> <user>xws-security-server</user> <password-callback-class> ping.PingPWCallback </password-callback-class> <signature-infos> <signature-info> <keyIdentifier>DirectReference</keyIdentifier> <keystore> <key-type>jks</key-type> <keystore-password>changeit</keystore-password> <keystore-filename> server-keystore.jks </keystore-filename> </keystore> </signature-info> </signature-infos> </response-sender> </security> </port> </service> </jeus-webservices-dd>
이에 JAX-WS (JEUS 6) 웹 서비스의 메시지 수준 보안은 웹 서비스를 생성할 때, 즉 wsgen 혹은 wsimport 통해 웹 서비스를 생성할 때 service-config.xml 파일을 추가적으로 -policy 인자와 함께 명령문에 설정한다.
[예 16.36] << service-config.xml >>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<web-services-config xmlns="http://www.tmaxsoft.com/xml/ns/jeus">
<policy>
<endpoint-policy-subject>
<security-policy>
<security-binding>
<symmetric-binding>
<protection-token>
<x509-token>
<include-token>true</include-token>
</x509-token>
</protection-token>
</symmetric-binding>
</security-binding>
<token>
<signed-supporting-token>
<username-token>
<username-password-validator>
fromjava.server.UsernamePasswordValidator
</username-password-validator>
<include-token>true</include-token>
</username-token>
</signed-supporting-token>
</token>
<keystore>
<keystore-file>
<alias>xws-security-server</alias>
<key-type>JKS</key-type>
<keystore-password>changeit</keystore-password>
<keystore-filename>
keystore.jks
</keystore-filename>
</keystore-file>
</keystore>
<wss-version>11</wss-version>
<protection>
<signed-part>
<body/>
</signed-part>
<encrypted-part>
<body/>
</encrypted-part>
</protection>
</security-policy>
</endpoint-policy-subject>
</policy>
</web-services-config>
JEUS 웹 서비스는 접근이 허용된 사용자만이 웹 서비스를 호출할 수 있도록 접근 제어 설정을 할 수 있으며, 웹 서비스 Back-end에 따라 각각 설정법이 다르다. JEUS 웹 서비스의 접근 제어 설정 방법은 “26.4. 접근 제어 설정”과 동일하며 클라이언트의 호출 방식만 다르다. 접근 제어(Basic Authentication)가 설정된 웹 서비스의 호출을 하기 위해서는 WSDL에 접근하여 그 내용을 바탕으로 Portable Artifact를 생성하고, 그것을 이용하여 웹 서비스를 호출해야 하는데, 이 경우에 사용자 이름과 암호를 요구할 경우 설정해 주는 작업이 필요하다.
wsimport 툴을 이용하여 Portable Artifact를 생성하기 위해서는 다음과 같이 콘솔 창에 입력한다.
C:\>wsimport -Xauthfile authorization.txt http://localhost:8088/AddNumbers/AddNumbersImplService?wsdl
"authorization.txt" 파일은 실제 WSDL에 접근하기 위한 권한 설정 파일이다. 권한 설정 파일의 예는 다음과 같다.
[예 16.37] << authorization.txt >>
http://jeus:jeus@localhost:8088/AddNumbers/AddNumbersImplService?wsdl
여기에서 사용자명은 jeus, 암호는 jeus이다.
JAX-WS 웹 서비스 클라이언트가 스스로 인증 하기 위해서는 다음과 같은 2가지의 설정이 클라이언트 프로그램 내에 삽입되어야 한다.
javax.xml.ws.BindingProvider.USERNAME_PROPERTY
javax.xml.ws.BindingProvider.PASSWORD_PROPERTY
다음 예는 실제로 프로그램 내에 어떻게 위 설정들이 삽입될 수 있는지를 보여준다.
Echo port = // … 서비스 엔드포인트 인터페이스의 획득
((javax.xml.ws.BindingProvider) port).getRequestContext().
put(javax.xml.ws.BindingProvider.USERNAME_PROPERTY, "jeus");
((javax.xml.ws.BindingProvider) port).getRequestContext().
put(javax.xml.ws.BindingProvider.PASSWORD_PROPERTY, "jeus");
String s = port.echoString("JEUS");
또한, 런타임에 JAX-WS 웹 서비스 클라이언트 엔진은 동적 Stub을 생성하기 위해 원격 WSDL에 한번 접근하는데, 이때 부가적인 권한 설정이 필요하다. 이러한 권한 설정은 java.net.Authenticator 클래스를 이용하여 클라이언트 프로그램에 설치한다.
다음은 java.net.Authenticator 클래스를 사용한 클라이언트 프로그램의 예이다.
[예 16.38] << AddNumberClient.java >>
public class AddNumbersClient { ... public void execute() { Authenticator.setDefault(new MyAuthenticator()); AddNumbersImpl port = new AddNumbersImplService() .getAddNumbersImplPort(); ((javax.xml.ws.BindingProvider) port).getRequestContext(). put(javax.xml.ws.BindingProvider.USERNAME_PROPERTY, "jeus"); ((javax.xml.ws.BindingProvider) port).getRequestContext(). put(javax.xml.ws.BindingProvider.PASSWORD_PROPERTY, "jeus"); int number1 = 10; int number2 = 20; port.addNumbers(number1, number2); ... } class MyAuthenticator extends Authenticator { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication("jeus", "jeus".toCharArray()); } } }