HoK(holder-of-key) 주제 확인 메소드를 포함한 자체 발행 SAML 토큰을 작성한 다음
JAX-WS(Java™ API for XML-Based Web Services)
프로그래밍 모델 및 WSS API(Web Services Security API)를 사용하여 웹 서비스 요청 메시지와 함께 해당 토큰을 전송할 수 있습니다.
시작하기 전에
이 태스크에서는 사용자가 JAX-WS
프로그래밍 모델, WSS API 인터페이스, SAML 개념 및
웹 서비스 설정을 구성하고 관리하기 위한 정책 세트 사용에 익숙한 것으로 가정합니다.
이 태스크를 시작하기 전에 다음 조치를 완료하십시오.
- WSS API를 사용한 자체 발행 SAML 전달자 토큰 전송에 대해 읽어 보십시오.
- 메시지 레벨 보호와 함께 WSS API를 사용한 자체 발행 SAML 전송자 인증 토큰 전송에 대해 읽어 보십시오.
이 태스크 정보
이 태스크는 HoK(holder-of-key) 주제 확인 메소드 보안 요구사항을 충족시키기 위해
선택한 SOAP 메시지의 디지털 서명을 생성하는 SAML 보안 토큰에 의해 식별되는 비대칭 키의 사용에 초점을 맞춥니다. 전송자의 X.509 인증서가 SAML 보안 토큰에 임베드됩니다. 전송자는
해당 개인 키를 사용하여 요청 메시지 요소의 선택한 파트에 서명하고 수신인의 공개 키를 사용하여
요청 메시지를 암호화합니다. 수신인은 수신인의 개인 키를 사용하여 응답 메시지의 선택한 요소에 서명하고
SAML 보안 토큰에 있는 전송자의 공개 키를 사용하여 응답 메시지의 선택한 요소를 암호화합니다. 웹 서비스 제공자에게
첨부된 웹 서비스 보안 정책이 참조용으로 제공됩니다.
프로시저
- HoK(holder-of-key) 주제 확인 메소드를 포함하는 SAML 보안 토큰을 작성하십시오. 예를 들면, 다음과 같습니다.
WSSFactory factory = WSSFactory.getInstance();
// Initialize WSSGenerationContext
com.ibm.websphere.wssecurity.wssapi.WSSGenerationContext gencont = factory.newWSSGenerationContext();
// Initialize SAML issuer configuration via custom properties
HashMap<Object, Object> customProps = new HashMap<Object,Object>();
customProps.put(SamlConstants.ISSUER_URI_PROP, "example.com");
customProps.put(SamlConstants.TTL_PROP, "3600000");
customProps.put(SamlConstants.KS_PATH_PROP, "keystores/saml-provider.jceks");
customProps.put(SamlConstants.KS_TYPE_PROP, "JCEKS");
customProps.put(SamlConstants.KS_PW_PROP, "{xor}LCswLTovPiws");
customProps.put(SamlConstants.KEY_ALIAS_PROP, "samlissuer");
customProps.put(SamlConstants.KEY_NAME_PROP, "CN=SAMLIssuer, O=EXAMPLE");
customProps.put(SamlConstants.KEY_PW_PROP, "{xor}NDomLz4sLA==");
customProps.put(SamlConstants.TS_PATH_PROP, "keystores/saml-provider.jceks");
customProps.put(SamlConstants.TS_TYPE_PROP, "JCEKS");
customProps.put(SamlConstants.TS_PW_PROP, "{xor}LCswLTovPiws");
gencont.add(customProps); //Add custom properties
HashMap<Object, Object> map = new HashMap<Object, Object>();
map.put(SamlConstants.CONFIRMATION_METHOD, "holder-of-key");
map.put(SamlConstants.Token_REQUEST, "issue");
map.put(SamlConstants.TOKEN_TYPE, WSSConstants.SAML.SAML20_VALUE_TYPE);
map.put(SamlConstants.SAML_NAME_IDENTIFIER, "Alice");
map.put(SamlConstants.SIGNATURE_REQUIRED, "true");
map.put(SamlConstants.KEY_TYPE,
"http://docs.oasis-open.org/ws-sx/ws-trust/200512/PublicKey");
map.put(SamlConstants.SAML_APPLIES_TO, "http://localhost:9080/your_Web_service");
map.put(SamlConstants.KEY_ALIAS, "soapinitiator" );
map.put(SamlConstants.KEY_NAME, "CN=SOAPInitator, O=ACME");
map.put(SamlConstants.KEY_PASSWORD, "keypass");
map.put(SamlConstants.KEY_STORE_PATH, "keystores/initiator.jceks");
map.put(SamlConstants.KEY_STORE_PASSWORD, "storepass");
map.put(SamlConstants.KEY_STORE_TYPE, "jceks");
SAMLGenerateCallbackHandler callbackHandler = new SAMLGenerateCallbackHandler(map);
SAMLToken samlToken = (SAMLToken) factory.newSecurityToken(SAMLToken.class,
callbackHandler, "system.wss.generate.saml");
전송자의 개인 키가 SamlConstants.KEY_ALIAS 특성에 의해 지정되고
요청 메시지의 선택된 요소에 서명하는 데 사용됩니다.
- WSSGenerationContext 오브젝트를 사용하여
요청 메시지 보안 헤더 처리를 준비하십시오. 예를 들면, 다음과 같습니다.
gencon.add(samlToken); //this line of code can be omitted
WSSTimestamp timestamp = factory.newWSSTimestamp();
gencon.add(timestamp);
WSSSignature sig = factory.newWSSSignature(samlToken);
sig.setTokenReference(SecurityToken.REF_KEYID);
//If the gencon.add(samlToken); line of code is omitted,
//the above line of code must be replaced with
//sig.setTokenReference(SecurityToken.REF_STR);
sig.setSignatureMethod(WSSSignature.RSA_SHA1);
sig.setCanonicalizationMethod(WSSSignature.EXC_C14N);
sig.addSignPart(WSSSignature.BODY);
sig.addSignPart(WSSSignature.TIMESTAMP);
sig.addSignPart(WSSSignature.ADDRESSING_HEADERS);
gencon.add(sig);
X509GenerateCallbackHandler x509callbackHandler2 = new X509GenerateCallbackHandler(
null,
"keystores/initiator.jceks",
"jceks",
"storepass".toCharArray(),
"soaprecipient",
null,
"", null);
SecurityToken st2 = factory.newSecurityToken(X509Token.class, x509callbackHandler2);
WSSEncryption enc = factory.newWSSEncryption(st2);
enc.addEncryptPart(WSSEncryption.BODY_CONTENT);
enc.addEncryptPart(WSSEncryption.SIGNATURE);
enc.setEncryptionMethod(WSSEncryption.AES256);
enc.setKeyEncryptionMethod(WSSEncryption.KW_RSA_OAEP);
gencon.add(enc);
이 예에서 암호화에 256비트 키 크기가 사용되므로 JCE(Java Cryptography
Extension) 정책 파일을 가져와야 합니다. 자세한 정보는 "웹 서비스 보안 애플리케이션 조정" 주제에서
무제한 JCE 정책 파일 사용에 대해 읽어 보십시오.
- WSSConsumingContext 오브젝트를 작성하여 응답 메시지 보안 헤더 처리를 준비하십시오. 예를 들면, 다음과 같습니다.
WSSConsumingContext concont = factory.newWSSConsumingContext();
HashMap<Object, Object> map = new HashMap<Object, Object>();
SAMLConsumerCallbackHandler callbackHandler = new SAMLConsumerCallbackHandler(map);
WSSDecryption dec = factory.newWSSDecryption(SAMLToken.class, callbackHandler,
"system.wss.consume.saml");
dec.addAllowedEncryptionMethod(WSSDecryption.AES256);
dec.addAllowedKeyEncryptionMethod(WSSDecryption.KW_RSA_OAEP);
dec.encryptKey(false);
dec.addRequiredDecryptPart(WSSDecryption.BODY_CONTENT);
concont.add(dec);
X509ConsumeCallbackHandler verHandler = new X509ConsumeCallbackHandler(null,
"keystores/initiator.jceks",
"jceks",
"storepass".toCharArray(),
"soaprecipient",
null, null);
WSSVerification ver = factory.newWSSVerification(X509Token.class, verHandler);
ver.addRequiredVerifyPart(WSSVerification.BODY);
concont.add(ver);
- JDK keytool 유틸리티를 사용하여 코드 예를 테스트하는 데 사용되는
saml-provider.jceks, initiator.jceks 및 recipient.jceks 파일을 생성하십시오. 예를 들면, 다음과 같습니다.
keytool -genkey -alias samlissuer -keystore saml-provider.jceks -dname "CN=SAMLIssuer, O=ACME" -storepass myissuerstorepass -keypass myissuerkeypass
-storetype jceks -validity 5000 -keyalg RSA -keysize 2048
keytool -genkey -alias soaprecipient -keystore recipient.jceks -dname "CN=SOAPRecipient, O=ACME" -storepass myreciptstorepass -keypass myreciptkeypass
-storetype jceks -validity 5000 -keyalg RSA -keysize 2048
keytool -genkey -alias soapinitiator -keystore initiator.jceks -dname "CN=SOAPInitator, O=ACME" -storepass myinitatstorepass -keypass myinitatkeypass
-storetype jceks -validity 5000 -keyalg RSA -keysize 2048
keytool -export -alias samlissuer -file issuerpub.cer -keystore saml-provider.jceks -storepass myissuerstorepass -storetype jceks
keytool -export -alias soaprecipient -file reciptpub.cer -keystore recipient.jceks -storepass myreciptstorepass -storetype jceks
keytool -export -alias soapinitiator -file initatpub.cer -keystore initiator.jceks -storepass myinitatstorepass -storetype jceks
keytool -import -alias samlissuer -file issuerpub.cer -keystore initiator.jceks -storepass myissuerstorepass -storetype jceks -keypass myissuerkeypass -noprompt
keytool -import -alias soaprecipient -file reciptpub.cer -keystore initiator.jceks -storepass myreciptstorepass -storetype jceks -keypass myreciptkeypass -noprompt
keytool -import -alias samlissuer -file issuerpub.cer -keystore recipient.jceks -storepass myreciptstorepass -storetype jceks -keypass myreciptkeypass -noprompt
keytool -import -alias soapinitiator -file initatpub.cer -keystore initiator.jceks -storepass myinitatstorepass -storetype jceks -keypass myinitatkeypass -noprompt
keytool -import -alias soapinitiator -file initatpub.cer -keystore saml-provider.jceks -storepass myissuerstorepass -storetype jceks -keypass myissuerkeypass -noprompt
결과
SOAP 메시지로 SAML 보안 토큰을 전송하고 메시지 레벨 보호의 SAML 보안에서 임베드되는 비대칭 키를 사용하는 웹 서비스 클라이언트 애플리케이션을 작성하기 위한 핵심 블록 빌드를 학습했습니다.
예
다음 예는 웹 서비스 제공자 웹 서비스 보안 정책을 보여줍니다.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200512" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:spe="http://www.ibm.com/xmlns/prod/websphere/200605/ws-securitypolicy-ext">
<wsp:Policy wsu:Id="response:app_encparts">
<sp:EncryptedElements>
<sp:XPath>/*[namespace-uri()='http://schemas.xmlsoap.org/soap/envelope/'
and local-name()='Envelope']/*[namespace-uri()='http://schemas.xmlsoap.org/soap/envelope/'
and local-name()='Header']/*[namespace-uri()='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'
and local-name()='Security']/*[namespace-uri()='http://www.w3.org/2000/09/xmldsig#' and local-name()='Signature']</sp:XPath>
<sp:XPath>/*[namespace-uri()='http://www.w3.org/2003/05/soap-envelope'
and local-name()='Envelope']/*[namespace-uri()='http://www.w3.org/2003/05/soap-envelope'
and local-name()='Header']/*[namespace-uri()='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'
and local-name()='Security']/*[namespace-uri()='http://www.w3.org/2000/09/xmldsig#' and local-name()='Signature']</sp:XPath>
</sp:EncryptedElements>
<sp:EncryptedParts>
<sp:Body/>
</sp:EncryptedParts>
</wsp:Policy>
<wsp:Policy wsu:Id="request:req_enc">
<sp:EncryptedParts>
<sp:Body/>
</sp:EncryptedParts>
</wsp:Policy>
<wsp:Policy wsu:Id="request:app_signparts">
<sp:SignedParts>
<sp:Body/>
<sp:Header Namespace="http://schemas.xmlsoap.org/ws/2004/08/addressing"/>
<sp:Header Namespace="http://www.w3.org/2005/08/addressing"/>
</sp:SignedParts>
<sp:SignedElements>
<sp:XPath>/*[namespace-uri()='http://schemas.xmlsoap.org/soap/envelope/'
and local-name()='Envelope']/*[namespace-uri()='http://schemas.xmlsoap.org/soap/envelope/'
and local-name()='Header']/*[namespace-uri()='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'
and local-name()='Security']/*[namespace-uri()='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd'
and local-name()='Timestamp']</sp:XPath>
<sp:XPath>/*[namespace-uri()='http://www.w3.org/2003/05/soap-envelope'
and local-name()='Envelope']/*[namespace-uri()='http://www.w3.org/2003/05/soap-envelope'
and local-name()='Header']/*[namespace-uri()='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'
and local-name()='Security']/*[namespace-uri()='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd'
and local-name()='Timestamp']</sp:XPath>
</sp:SignedElements>
</wsp:Policy>
<wsp:Policy wsu:Id="response:resp_sig">
<sp:SignedParts>
<sp:Body/>
</sp:SignedParts>
</wsp:Policy>
<sp:AsymmetricBinding>
<wsp:Policy>
<sp:InitiatorToken>
<wsp:Policy>
<spe:CustomToken sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200512/IncludeToken/Always"/>
<wsp:Policy>
<spe:WssCustomToken localname="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0"/>
</wsp:Policy>
</spe:CustomToken>
</wsp:Policy>
</sp:InitiatorToken>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic256/>
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:IncludeTimestamp/>
<sp:RecipientToken>
<wsp:Policy>
<sp:X509Token sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200512/IncludeToken/Always"/>
<wsp:Policy>
<sp:WssX509V3Token11/>
</wsp:Policy>
</sp:X509Token>
<wsp:Policy>
<sp:RecipientToken>
<sp:Layout>
<wsp:Policy>
<sp:Strict/>
</wsp:Policy>
</sp:Layout>
<wsp:Policy>
<sp:AsymmetricBinding>
</wsp:Policy>