내용 목차
본 장에서는 전송 수준과 메시지 수준의 웹 서비스 보안에 대해 자세히 설명하고, JEUS 웹 서비스에서 이러한 보안을 적용하는 방법에 대해 설명한다.
웹 서비스에 보안을 적용하기 위해서는 전통적으로 다음과 같은 2가지 방식이 존재한다.
전송 수준 보안(Transport-level Security)
SSL을 사용하여 클라이언트와 웹 서비스 사이의 연결 보안을 보장한다.
전송 수준 보안을 적용하려면 클라이언트와 JEUS 서버 간의 연결을 SSL을 사용하여 안전하게 할 수 있다. 그러나 이러한 방식은 연결 자체만을 안전하게 하며 클라이언트와 JEUS 서버 사이에 라우터나 메시지 큐와 같은 매개체(Intermediary)가 있다면 매개체는 SOAP 메시지를 암호화되지 않은 읽히기 쉬운 텍스트 문서 형태로 가질 수 있다. 또한 전송 수준 보안은 전체적인 메시지를 다루므로 메시지 일부의 보안 적용이 불가능하다.
SOAP 메시지를 전자 서명이나 암호화한다.
메시지 수준 보안은 SSL의 보안의 장점을 포함하면서 부가적인 유연성을 제공한다. 메시지 수준 보안은 메시지 전달 과정에서 하나 이상의 매개체가 존재하더라도 보안이 유지되는 End-to-End 보안이다. 연결 자체의 보안 유지보다는 SOAP 메시지 자체의 서명과 암호화를 의미한다. 또한 부분적인 서명과 암호화가 가능하다는 장점이 있다.
웹 서비스의 전송 수준 보안은 웹 서비스 클라이언트 응용 프로그램과 웹 서비스 간의 연결을 SSL을 사용하여 안전하게 하는 것을 의미한다.
전체적인 절차는 다음과 같다.
JEUS 서버의 SSL을 설정한다.
웹 서비스 개발 부분은 추가 작업이 필요하지 않다. JEUS 서버에서의 SSL 설정은 "JEUS Web Engine 안내서"를 참조한다.
다음의 과정으로 클라이언트 응용 프로그램의 SSL을 설정한다.
인증서를 가져온다(Internet Explorer 등을 통해 인증서를 로컬 디렉터리에 저장한다).
가져온 인증서를 Keystore에 저장한다.
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-SecurityPolicy) 명세는 어떻게 메시지가 보안화되어 이동되는지를 설명하는 전제(assertion)들을 정의한다. 이러한 전제들은 토큰, 암호화 기법, 사용되는 메커니즘, 전송 보안 등의 정책들을 포괄하는 유연성을 따른다. 이러한 웹 서비스 보안 정책은 웹 서비스 메시지 수준 보안을 구현할 때 핵심적인 요소이다.
JEUS 웹 서비스에서는 여러 가지 웹 서비스 메시지 수준 보안을 위한 시나리오별 예제들을 제공한다. 이러한 시나리오별 예제의 웹 서비스 보안 정책을 적용한 정책 파일들은 여러 가지 웹 서비스의 메시지 보안을 적용하는 데 도움이 될 것이다.
웹 서비스 보안(WS-Security) 명세는 메시지의 XML 서명을 사용한 데이터 무결성과 XML 암호화를 사용한 데이터 비밀성 2가지를 실현하여 안전한 웹 서비스를 구현할 때 사용되는 확장된 SOAPElement들을 정의하고 있다.
다음은 웹 서비스 보안 명세를 사용한 웹 서비스 보안 시나리오이다.
사용자명 인증(Username Authentication)을 통한 대칭 바인딩의 인증 기능 강화
상호 인증 보안
SSL을 통한 SAML 인증
이 예제는 대칭 바인딩(Symmetric Binding)을 통한 메시지 보안 예제이다. 앞서 설명한 것과 마찬가지로 대칭 바인딩에서는 클라이언트와 서버가 암호화 키와 서명에 동일한 인증서 정보를 사용한다. 이 예제에서는 그 인증서 정보로써 서버의 인증서를 사용한다. 이때 클라이언트는 자신이 누구인지를 서버에 인증받을 방법이 별도로 존재하지 않기 때문에 부가적으로 사용자명 토큰을 사용한다.
다음은 사용자명 인증(Username Authentication)의 시나리오와 Keystore 설정에 대한 설명이다.
시나리오
다음은 사용자명 인증의 시나리오이다.
클라이언트는 대칭 키를 생성한 후 이를 사용해 요청 메시지를 암호화 및 서명을 한다. 이때 서버의 공개 키를 사용하여 대칭 키를 함께 메시지에 담아 보낸다. 추가적으로 사용자명과 비밀번호 정보를 함께 보낸다.
서버는 서버의 개인 키를 사용하여 대칭 키를 해독한 뒤 이를 사용하여 클라이언트의 요청 메시지를 복호화하고 서명을 검증한다. 추가적으로 사용자명과 비밀번호를 통해 클라이언트를 인증한다.
서버는 다시 그 대칭 키를 통해 응답 메시지를 서명 및 암호화한다. 이때 대칭 키를 별도로 클라이언트로 전송하지는 않는다.
클라이언트는 가지고 있던 대칭 키를 사용하여 서버의 응답 메시지를 해석하고 서명을 확인한다.
Keystore 설정
다음은 Keystore 설정 정보이다.
구분 | 설명 |
---|---|
클라이언트 | 서버의 공개 키가 담긴 Keystore이다. |
서버 | 서버의 개인 키가 담긴 Keystore이다. |
이 예제는 비대칭 바인딩, 상호 인증서를 통한 메시지 보안 예제이다. 대칭 바인딩과 달리 비대칭 바인딩에서는 클라이언트와 서버가 암호화 키와 서명에 서로 다른 인증서 정보를 사용한다. 서로 자신의 개인 키로 서명을 하고 인증서 정보를 넘겨줌으로써 서로 서명을 검증할 때 상대편이 누구인지를 인증할 수 있다.
다음은 상호 인증 보안 시나리오와 Keystore 설정에 대한 설명이다.
시나리오
다음은 상호 인증 보안 (Mutual Certificates Security)의 시나리오이다.
클라이언트는 클라이언트의 개인 키로 메시지에 서명을 하고 하나의 대칭 키를 생성해서 메시지를 암호화한 후, 그 대칭 키를 서버의 공개 키를 사용하여 암호화하여 메시지와 함께 서버에게 요청 메시지를 보낸다. 이때 인증 역할을 하게 될 클라이언트의 인증서를 함께 보낸다.
서버는 서버의 개인 키를 사용하여 대칭 키를 꺼낸 후 암호화된 메시지를 해석한다. 인증서를 통해 인증을 하고 클라이언트의 공개 키로 서명을 검증한다.
서버는 서버의 개인 키로 메시지에 서명을 하고 하나의 대칭 키를 생성해서 메시지를 암호화한 후 그 대칭 키를 클라이언트의 공개 키를 사용하여 암호화하며 메시지와 함께 클라이언트에게 응답 메시지를 보낸다. 이때 인증 역할을 하게 될 서버의 인증서는 함께 보내지 않는다.
클라이언트는 클라이언트의 개인 키를 사용하여 대칭 키를 꺼낸후 암호화된 메시지를 해석한다. 서버의 공개 키로 서명을 확인한다.
Keystore 설정
다음은 Keystore 설정 정보이다.
구분 | 설명 |
---|---|
클라이언트 | 서버의 공개 키가 담긴 Keystore이다. |
서버 | 서버의 개인 키가 담긴 Keystore이다. |
본 절에서는 SAML(Security Assertions Mark-up Language) 토큰을 SOAP 메시지 Header에 포함시켜 보내는 방법에 대해 설명한다.
실제 웹 서비스에서 SAML 토큰을 사용한 서비스를 하려면 이러한 SAML 토큰을 생성하는 SAML 토큰 프레임워크가 필요하다. 여기서는 단순히 핸들러를 통해 SAML 토큰을 텍스트로 생성해서 보내는 예를 통해 어떻게 SAML 토큰을 SOAP 메시지 Header에 포함시키는지에 대해 알 수 있다.
웹 서비스의 발전과 사용자의 활용 빈도가 높아짐에 따라 다양한 웹 애플리케이션 간에 보안 및 인증 정보를 교환할 필요성이 높아지고 이에 따른 교환 표준이 필요하다. 이와 같은 표준을 제공하기 위해 탄생한 언어가 SAML이다.
SAML은 다음과 같은 기능을 제공한다.
사용자 보안 정보에 대한 XML 포맷을 제공하고 이러한 정보를 요청 및 전송하기 위한 포맷을 제공한다.
SOAP과 같은 프로토콜에서 이러한 메시지를 사용하는 방법을 정의한다.
웹 SSO와 같이 일반적인 특정 사용 사례에 대해 자세한 메시지 교환 방법을 지정한다.
사용자의 신원을 Export시키지 않고 사용자 속성을 결정하는 기능을 비롯하여 여러 가지 개인 정보 보호 메커니즘을 지원한다.
UNIX, Microsoft Windows, X.509, LDAP, DCE, XCML 등 널리 사용되는 기술에서 제공하는 포맷으로 ID 정보를 처리하는 방법을 제공한다.
메타 데이터 스키마를 수식화하여 참여하는 시스템에서 지원하는 SAML 옵션과 통신할 수 있는 기능을 제공한다.
다음은 SSL을 통한 SAML 인증을 사용하기 위한 시나리오이다.
시나리오
클라이언트는 SAML 토큰을 SOAP 메시지 Header에 포함하여 SSL 설정을 통해 메시지를 보낸다.
서버는 SOAP 메시지 Header에 포함된 SAML 토큰을 해석하고 응답 메시지를 보낸다.
모든 클라이언트와 서버의 메시지 교환은 JEUS 서버의 SSL 설정을 통해 이루어진다.
웹 서비스 보안 대화(Web Service Secure Conversation) 명세는 서비스 제공자와 클라이언트 간의 보안 컨텍스트 생성 및 공유를 정의한다. 보안 컨텍스트는 메시지를 교환할 때 생기는 간접비용(overhead)을 줄이기 위해 사용된다. 이 명세는 보다 나은 메시지 수준의 보안과 보다 효율적인 다중 메시지 교환을 제공하기 위한 표준을 정의한다.
이 명세를 따르고 있는 JEUS 웹 서비스는 다중 메시지 교환을 위한 보안 방식이 정의되는 기본 메커니즘을 제공하고 더욱 더 효율적인 키나 새로운 키 재료와 함께 컨텍스트가 수립되도록 한다. 이러한 접근은 전체적인 성능과 다음에 따르는 메시지 교환의 보안성을 향상시킨다.
대칭 바인딩에서는 메시지를 여러 번 주고받을 때마다 암호화 키를 매번 생성해야 한다. 따라서 메시지를 여러 번 주고받는 시나리오에서는 적합하지 않다. 이 예제에서는 보안 대화(Secure Conversation)를 통해 첫 메시지를 주고받기 전 Handshaking 과정을 통해 비대칭 바인딩으로 서로 SecureContext를 수립하고 이후 실제 메시지를 여러 번 주고받을 때는 수립한 SecureContext를 사용하여 대칭 바인딩과 같이 서명과 암호화에 사용하게 된다. 인증 과정은 처음 비대칭 바인딩을 통한 SecureContext 수립 과정에서 거치게 된다.
다음은 웹 서비스 보안 대화의 시나리오와 Keystore 설정에 대한 설명이다.
시나리오
다음은 웹 서비스 보안 대화의 시나리오이다.
클라이언트는 자신의 인증서와 SecureContext 정보를 자신의 인증서를 사용해서 서명하고, 서버의 공개 키로 암호화하여 서버에 전송한다(비대칭 바인딩).
서버는 자신의 개인 키로 클라이언트의 메시지를 복호화하고 클라이언트 서명을 검증하면서 인증 절차를 거친후 SecureContext 수립 메시지로 응답한다(비대칭 바인딩).
이후 클라이언트와 서버는 메시지를 주고받을 때 이 SecureContext 정보를 통해 암호화 및 서명을 한다(대칭 바인딩).
Keystore 설정
다음은 Keystore 설정 정보이다.
구분 | 설명 |
---|---|
클라이언트 | 클라이언트의 개인 키와 서버의 공개 키가 담긴 Keystore이다. |
서버 | 서버의 개인 키와 클라이언트의 공개 키가 담긴 Keystore이다. |
본 절에서는 WS-Trust를 인증에 관해 사용하는 예에 대해 살펴본다. 서로 다른 토큰, 즉 신뢰할 수 없는 관계의 인증서는 STS를 통해 SAML 토큰이라는 다른 형태로 변환되어 요청자를 신뢰할 수 없는 응답자가 STS를 통해 인증할 수 있다.
웹 서비스 보안을 사용하는 메시지 교환 방식에서는 서비스와 클라이언트 간에 보안 정보 공유를 위해 사용되는 보안 토큰에 대해 이미 합의되어야 하지만, 이러한 사전 합의가 이루어지지 않는 경우 메시지 교환 이전에 신뢰 관계(Trust Relationship)가 성립되어야 한다. 이러한 것을 웹 서비스 신뢰(Web Service Trust)라고 하며 JEUS 웹 서비스는 이를 지원하고 있다.
웹 서비스 신뢰는 서버와 클라이언트가 서로 다른 형태의 보안 토큰 또는 서로 다른 도메인의 보안 토큰을 사용해서 서로를 인증하지 못하는 상황일 때 사용할 수 있다. 이러한 클라이언트와 서버의 상이한 보안 토큰때문에 서로를 인증하지 못하는 상황은 클라이언트와 서버 사이에 각각의 인증 역할을 중계해 주는 또 다른 웹 서비스가 존재하여 해결한다. 이러한 웹 서비스를 통상적으로 STS(Security Token Service)라고 한다.
웹 서비스 신뢰는 다음의 관계를 갖는다.
클라이언트와 서버는 서로 직접적인 신뢰 관계가 없다.
클라이언트와 STS는 서로 신뢰 관계가 있다.
STS와 서버는 서로 신뢰 관계가 있다.
다음 그림과 같이 Requestor는 웹 서비스와 통신하기 전에 웹 서비스가 자신을 인증할 수 있도록 하는 보안 토큰을 STS로부터 동적으로 부여받는다. 부여받은 보안 토큰을 통해 Requestor는 웹 서비스에게 실제로 보내려는 메시지에 STS로 부여받은 보안 토큰을 함께 실어 보내게 되며 웹 서비스는 Requestor를 인증(신뢰)할 수 있다.
(출처: http://docs.oasis-open.org/ws-sx/ws-trust/200512/ws-trust-1.3-os.html)
다음은 웹 서비스 신뢰 시나리오와 Keystore 설정에 대한 설명이다.
시나리오
다음은 웹 서비스 신뢰의 시나리오이다.
클라이언트는 자신의 인증서, 사용자명, 암호와 함께 실제 메시지를 전달할 서버에 대한 SAML 인증서 발급을 STS에 요청한다.
STS는 클라이언트를 인증한 후 SAML 인증서를 발급한다.
클라이언트는 SAML 인증서와 함께 서버에 메시지를 보낸다.
서버는 SAML 인증서를 통해 클라이언트를 신뢰하고 비즈니스 로직을 수행한다.
Keystore 설정
다음은 Keystore 설정 정보이다.
구분 | 설명 |
---|---|
클라이언트 | - 클라이언트의 개인 키와 서버의 공개 키가 담긴 Keystore이다. - 클라이언트의 개인 키와 STS 서버의 공개 키가 담긴 Keystore이다. |
서버 | 서버의 개인 키와 클라이언트의 공개 키가 담긴 Keystore이다. |
STS 서버 | 서버의 개인 키와 클라이언트의 공개 키가 담긴 Keystore이다. |
본 절에서는 JEUS 웹 서비스 메시지 수준 보안의 여러 가지 시나리오 예제에서 공통적으로 적용되는 설정법과 각각의 시나리오에 대한 설정법을 자세히 살펴볼 것이다. 실제 여러 가지 시나리오 예제에서 동작하는 것에 대해서는 샘플을 참고한다.
각 시나리오별 메시지 보안 설정 예제의 웹 서비스와 클라이언트의 비즈니스 로직은 모두 동일하다.
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'에 들어가는 Keystore 파일에 대한 설정은 절대 경로 혹은 상대 경로를 포함한 실제 Keystore 파일의 위치를 지정한다. 상대 경로로 지정할 때는 서비스 구현 클래스가 포함된 classes 디렉터리 하위의 META-INF 디렉터리에 Keystore 파일이 위치해야 한다.
[예 17.1] 서버 메시지 수준 보안 설정 (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="7.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' 속성은 메시지에 토큰을 포함할 것인지의 여부를 설정한다.
X509 토큰에서 사용되는 예는 다음과 같다.
[예 17.2] 서버 메시지 수준 보안 설정 (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="7.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' 스키마 및 "JEUS Reference Book"이나 sample 예제를 참고한다.
Java 클래스로부터 웹 서비스 메시지 보안을 구현하기 위해서는 다음과 같이 wsgen 툴의 -policy 기능을 사용하여 웹 서비스를 구성한다.
$ 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 보안 정책 스키마는 다음과 같이 'endpoint-policy-subject', 'operation-policy-subject', 'input(output)-message-policy-subject' element에 보안 설정을 할 수 있다.
[예 17.3] 서버 Java 클래스 메시지 수준 보안 설정 (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="7.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 버전 등 메시지 보안에 관련된 여러 가지를 설정할 수 있다.
[예 17.4] 서버 Java 클래스 메시지 수준 보안 설정 (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="7.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' 중 하나를 선택할 수 있다.
[예 17.5] 서버 Java 클래스 메시지 수준 보안 설정 (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="7.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와 같은 것을 사용하여 메시지를 보호하겠다는 것을 나타낸다.
[예 17.6] 서버 Java 클래스 메시지 수준 보안 설정 (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="7.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 메시지의 Header 부분에 추가적인 element(EncryptedKey) 하위에 암호화된 상태로 메시지와 함께 전송되는데, 이 대칭 키를 암호화하거나 복호화할 때 사용되는 토큰이 같다는 것을 의미한다. 서명할 때도 서명을 검증할 때와 같은 토큰을 통하여 이루어진다는 것을 의미한다. 하위의 'protection-token' element는 추가적으로 메시지 암호화 및 서명에 사용되는 토큰이 동일함을 의미한다.
[예 17.7] 서버 Java 클래스 메시지 수준 보안 설정 (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="7.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 메시지의 Header 부분에 추가적인 element(EncryptedKey) 하위에 암호화된 상태로 메시지와 함께 전송되는데, 이 대칭 키를 암호화하거나 복호화할 때 사용되는 토큰이 서로 다르다는 것을 의미한다. 서명을 할 때와 서명을 검증할 때 다른 토큰을 통해 이루어진다는 것을 의미한다.
[예 17.8] 서버 Java 클래스 메시지 수준 보안 설정 (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="7.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>
다음은 하위의 element에 대한 설명이다.
element | 설명 |
---|---|
initiator-token | 클라이언트가 메시지를 서명할 때 사용하는 토큰이자 서버로부터 받은 암호화된 메시지를 복호화할 때 사용하는 토큰임을 의미한다. 서버가 메시지를 암호화할 때 사용하는 토큰이자 클라이언트로부터 받은 메시지의 서명을 검증할 때 사용하는 토큰임을 의미한다. |
recipient-token | 서버가 메시지를 서명할 때 사용하는 토큰이자 클라이언트로부터 받은 암호화된 메시지를 복호화할 때 사용하는 토큰임을 의미한다. 클라이언트가 메시지를 암호화할 때 사용하는 토큰이자 서버로부터 받은 메시지의 서명을 검증할 때 사용하는 토큰임을 의미한다. |
다음은 token element 보안 설정에 대한 예로 하위의 element 중 하나를 선택할 수 있다.
[예 17.9] 서버 Java 클래스 메시지 수준 보안 설정 (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="7.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>
다음은 하위의 element에 대한 설명이다.
element | 설명 |
---|---|
supporting-token | 이곳에 설정한 토큰 값은 실제 메시지의 Header 부분에 포함되며 다른 메시지 부분을 암호화하거나 서명할 때 사용할 수 있다. |
signed-supporting-token | 'supporting-token'과 같다. 추가적으로 이 토큰 또한 서명이 된다. |
endorsing-supporting-token | 서명을 다시 서명하는 데 사용되는 토큰을 설정할 때 사용한다. 'Signature' element를 전체를 서명한다. |
signed-endorsing-supporting-token | 'endorsing-supporting-token'과 같다. 추가적으로 이 토큰 또한 원래 서명을 통해 서명한다. 상호 서명하는 것을 의미한다. |
다음은 protection element 보안 설정에 대한 예로 하위의 element 중 하나를 선택할 수 있다.
[예 17.10] 서버 Java 클래스 메시지 수준 보안 설정 (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="7.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>
다음은 하위의 element에 대한 설명이다.
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'로 함께 설정해야 한다. 자세한 사항은 샘플을 참고한다. |
'operation-policy-subject' element의 보안 설정
서비스 구현 클래스의 메소드 단위로 보안 설정을 할 수 있다. 서명 및 암호화, 이를 뒷받침하는 보안 토큰들을 추가로 설정할 수 있다.
'operation-policy-subject' element 보안 설정은 서비스 구현 클래스의 메소드 단위의 보안 설정으로 다음과 같이 크게 2가지로 구분할 수 있다.
[예 17.11] 서버 Java 클래스 메시지 수준 보안 설정 (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="7.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>
다음은 하위의 element에 대한 설명이다.
element | 설명 |
---|---|
supporting-token | 이 설정은 'endpoint-policy-subject' element의 'token' element와 같다. 단, 이 설정은 이 메소드에만 설정되는 값이다. |
protection | 이 설정은 'endpoint-policy-subject' element의 'protection' element와 같다. 단, 이 설정은 이 메소드에만 설정되는 값이다. |
'input(output)-message-policy-subject' element의 보안 설정
서비스 구현 클래스 메소드의 매개변수 및 반환값 단위로 보안 설정을 한다. 서명 및 암호화와 이를 뒷받침하는 보안 토큰들을 추가로 설정할 수 있다.
'input(output)-message-policy-subject' element 보안 설정은 서비스 구현 클래스 메소드의 매개변수 및 반환값 단위 보안 설정으로 다음과 같이 크게 2가지로 구분할 수 있다.
[예 17.12] 서버 Java 클래스 메시지 수준 보안 설정 (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="7.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>
다음은 하위의 element에 대한 설명이다.
element | 설명 |
---|---|
supporting-token | 이 설정은 'endpoint-policy-subject' element의 'token' element와 같다. 단, 이 설정은 이 메소드의 매개변수 및 반환값에만 설정되는 값이다. |
protection | 이 설정은 'endpoint-policy-subject' element의 'protection' element와 같다. 단, 이 설정은 이 메소드의 매개변수 및 반환값에만 설정되는 값이다. |
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 예이다. Keystore에 대한 설정은 절대 경로 또는 상대 경로를 포함한 실제 Keystore 파일의 위치를 지정한다. 상대 경로로 지정할 때는 서비스 구현 클래스가 포함된 classes 디렉터리 하위의 META-INF 디렉터리에 Keystore 파일이 위치해야 한다.
[예 17.13] WSDL 메시지 수준 보안 설정 : << 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:SymmetricBindingxmlns: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:Wss11xmlns: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:ValidatorConfigurationxmlns:sc= "http://schemas.sun.com/2006/03/wss/server"> <sc:Validator name="usernameValidator" classname="com.tmax.UsernamePasswordValidator" /> </sc:ValidatorConfiguration> <ns9:UsingAddressingxmlns: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:EncryptedPartsxmlns:ns11= "http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <ns11:Body /> </ns11:EncryptedParts> <ns12:SignedPartsxmlns:ns12= "http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <ns12:Body /> <ns12:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing" /> <ns12:HeaderNamespace="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:SignedSupportingTokensxmlns: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:EncryptedPartsxmlns:ns15="http://schemas.xmlsoap.org/ws/ 2005/07/securitypolicy"> <ns15:Body /> </ns15:EncryptedParts> <ns16:SignedPartsxmlns:ns16="http://schemas.xmlsoap.org/ws/ 2005/07/securitypolicy"> <ns16:Body /> <ns16:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing"/> <ns16:HeaderNamespace="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:PolicyReferencexmlns: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:PolicyReferencexmlns:ns18="http://schemas.xmlsoap.org/ws/2004/09/policy" URI="#NewWebServicePortBinding_add_Input_Policy" /> <soap:body use="literal" /> </input> <output> <ns19:PolicyReferencexmlns: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:addresslocation="http://localhost:8088/usernameAuthentication_war/ NewWebServiceService"/> </port> </service> </definitions>
메시지 보안이 설정된 웹 서비스의 클라이언트는 wsit-client.xml 파일을 통해 다음과 같이 부가적으로 Keystore 및 Callback 핸들러 등을 설정해야 한다. 그 밖의 다른 메시지 보안 설정은 서버의 WSDL에 설정된 메시지 보안 정책을 런타임에 해석하여 메시지 보안 환경을 자동으로 구성한다.
Keystore에 대한 설정은 절대 경로 또는 상대 경로를 포함한 실제 Keystore 파일의 위치를 지정한다. 상대 경로로 지정할 때는 서비스 구현 클래스가 포함된 classes 디렉터리 하위의 META-INF 디렉터리에 Keystore 파일이 위치해야 한다.
[예 17.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) 클래스를 작성한다.
다음은 웹 서비스 설정 파일 작성에 대한 예이다.
[예 17.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한다.
[예 17.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에 Keystore(Truststore) 설정과 함께 사용자명 핸들러를 설정해야 한다.
wsit-client.xml 파일에 다음과 같이 설정한다.
[예 17.17] Keystore(Truststore) 설정 및 사용자명 핸들러의 설정 : <<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객체를 사용하여 사용자로부터 직접 입력받을 수도 있다.
[예 17.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"); } } } }
본 절에서는 서버와 클라이언트에서 상호 인증 보안(Mutual Certificates Security)을 설정하는 방법에 대해 설명한다.
서버의 웹 서비스 설정은 service-config.xml 설정 파일로 구성한다.
[예 17.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) 설정을 해야 한다.
[예 17.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>
본 절에서는 서버와 클라이언트에서 SSL을 통한 SAML 인증을 설정하는 방법에 대해서 설명한다.
서버의 웹 서비스 설정은 service-config.xml 설정 파일로 구성한다.
[예 17.21] 서버 SSL을 통한 SAML 인증 설정 : << 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 메시지 처리를 위한 Callback 핸들러 클래스 설정을 해야 한다.
wsit-client.xml 파일에 다음과 SAML 메시지 처리를 위한 Callback 핸들러 클래스를 설정한다.
[예 17.22] Callback 핸들러 클래스 설정 : << 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이다.
[예 17.23] Callback 핸들러 클래스 작성 : << 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() {...} ... }
본 절에서는 서버와 클라이언트에서 보안 대화(Secure Conversation)를 설정하는 방법에 대해서 설명한다.
웹 서비스의 서버 설정은 service-config.xml 설정 파일로 구성한다.
[예 17.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) 설정을 해야 한다.
[예 17.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>
본 절에서는 웹 서비스 신뢰를 위한 서버와 STS, 클라이언트의 설정 방법에 대해서 설명한다.
웹 서비스의 서버 설정은 service-config.xml 설정 파일로 구성한다.
[예 17.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>
STS를 위해 WS-SecurityPolicy 설정을 WSDL의 WS-Policy 프레임워크을 통해 설정해야 한다.
다음은 WS-SecurityPolicy 설정에 대한 예이다.
[예 17.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:ServiceProviderendPoint="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) 설정을 해야 한다.
[예 17.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에서는 추가적으로 service-config.xml을 통해 웹 서비스 정책 설정을 지원하며 이는 웹 서비스 보안 정책을 지원한다. 따라서 사용자가 웹 서비스 정책 및 웹 서비스 정책에 대해 모르더라도 서버와 클라이언트 간에 이러한 service-config.xml 파일의 공유가 가능하다면 이 파일을 통해 양 끝단의 메시지 수준의 보안을 간단하게 처리할 수 있다. 이는 JAX-RPC(JEUS 5) 웹 서비스의 메시지 수준 보안 방식과 유사하다.
웹 서비스 메시지 수준 보안에서 암호화(Encryption)에 대한 설정은 다음과 같이 구분된다.
JAX-RPC(JEUS 5) 웹 서비스 설정
JAX-WS(JEUS 7) 웹 서비스 설정
JAX-RPC(JEUS 5) 웹 서비스 메시지 수준 보안에서 암호화를 설정하는 방식은 다음과 같이 jeus-webservices-dd.xml(서버)와 jeus-web-dd.xml(클라이언트)를 설정한다.
[예 17.29] JAX-RPC 웹 서비스 암호화 설정 : << 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 7) 웹 서비스의 메시지 수준 보안은 웹 서비스를 생성(wsgen 또는 wsimport 통해 웹 서비스를 생성)할 때 service-config.xml 파일을 추가적으로 -policy 인자와 함께 명령문에 설정한다.
[예 17.30] JAX-WS(JEUS 7) 웹 서비스 암호화 설정 : << 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>
웹 서비스 메시지 수준 보안에서 서명(Signature)에 대한 설정은 다음과 같이 구분된다.
JAX-RPC(JEUS 5) 웹 서비스 설정
JAX-WS(JEUS 7) 웹 서비스 설정
JAX-RPC(JEUS 5) 웹 서비스 메시지 수준 보안에서는 다음과 같이 jeus-webservices-dd.xml(서버) 또는 jeus-web-dd.xml(클라이언트)으로 서명을 설정한다.
[예 17.31] JAX-RPC 웹 서비스 서명 설정 : << 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 7) 웹 서비스의 메시지 수준 보안은 웹 서비스를 생성(wsgen 혹은 wsimport 통해 웹 서비스를 생성)할 때 service-config.xml 파일을 추가적으로 -policy 인자와 함께 명령문에 설정한다.
[예 17.32] JAX-WS 웹 서비스 서명 설정 : << 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>
웹 서비스 메시지 수준 보안에서 Timestamp의 설정은 다음과 같이 구분된다.
JAX-RPC(JEUS 5) 웹 서비스 설정
JAX-WS(JEUS 7) 웹 서비스 설정
JAX-RPC(JEUS 5) 웹 서비스 메시지 수준 보안에서는 다음과 같이 jeus-webservices-dd.xml(서버) 또는 jeus-web-dd.xml(클라이언트)로 Timestamp를 설정한다.
[예 17.33] JAX-RPC(JEUS 5) 웹 서비스 Timestamp 설정 : << 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 7) 웹 서비스의 메시지 수준 보안은 웹 서비스를 생성할 때, 즉 wsgen 또는 wsimport로 웹 서비스를 생성할 때 service-config.xml 파일을 추가적으로 -policy 인자와 함께 명령문에 설정한다.
[예 17.34] JAX-WS(JEUS 7) 웹 서비스 Timestamp 설정 : << 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>
웹 서비스 메시지 수준 보안에서 사용자명 토큰(Username Token)의 설정은 다음과 같이 구분된다.
JAX-RPC(JEUS 5) 웹 서비스 설정
JAX-WS(JEUS 7) 웹 서비스 설정
JAX-RPC(JEUS 5) 웹 서비스 메시지 수준 보안에서는 다음과 같이 jeus-webservices-dd.xml(서버) 또는 jeus-web-dd.xml (클라이언트)로 Timestamp를 설정한다.
[예 17.35] JAX-RPC(JEUS 5) 웹 서비스 사용자명 토큰 설정 : << 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 7) 웹 서비스의 메시지 수준 보안은 웹 서비스를 생성(wsgen 또는 wsimport 통해 웹 서비스를 생성)할 때 service-config.xml 파일을 추가적으로 -policy 인자와 함께 명령문에 설정한다.
[예 17.36] JAX-WS(JEUS 7) 웹 서비스 사용자명 토큰 설정 : << 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를 생성하고, 그것을 사용하여 웹 서비스를 호출해야 하는데, 이 경우에 사용자 이름과 암호를 요구할 경우 설정하는 작업이 필요하다.
접근 제어가 설정된 웹 서비스의 클라이언트를 위한 Portable Artifact의 생성하는 과정이 필요한다.
wsimport 툴을 사용하여 Portable Artifact를 생성하기 위해서는 다음과 같이 콘솔 창에 입력한다.
$ wsimport -Xauthfile authorization.txt
http://localhost:8088/AddNumbers/AddNumbersImplService?wsdl
"authorization.txt" 파일은 실제 WSDL에 접근하기 위한 권한 설정 파일이다. 권한 설정 파일의 예는 다음과 같다.
[예 17.37] 권한 설정 파일 : << authorization.txt >>
http://jeus:jeus@localhost:8088/AddNumbers/AddNumbersImplService?wsdl
여기에서 사용자명은 'jeus', 암호는 'jeus'이다.
JAX-WS 웹 서비스 클라이언트가 스스로 인증하기 위해서는 다음과 같은 2가지의 설정이 클라이언트 프로그램 내에 삽입되어야 한다.
다음 예는 실제로 프로그램에서 위 설정을 구현한 예이다.
Echo port = // … SEI(Service Endpoint Interface)의 획득
((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 클래스를 사용한 클라이언트 프로그램의 예이다.
[예 17.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()); } } }