메시지 레벨 보호와 함께 WSS API를 사용하여 자체 발행 SAML 전송자 인증 토큰 전송
전송자 인증 주제 확인 메소드를 포함한 자체 발행 SAML 토큰을 작성한 다음 메시지 레벨 보호와 함께 JAX-WS(Java™ API for XML-Based Web Services) 프로그래밍 모델 및 WSS API(Web Services Security API)를 사용하여 웹 서비스 요청 메시지와 해당 토큰을 전송할 수 있습니다.
시작하기 전에
이 태스크에서는 사용자가 JAX-WS 프로그래밍 모델, WSS API 인터페이스, SAML 개념 및 웹 서비스 설정을 구성하고 관리하기 위한 정책 세트 사용에 익숙한 것으로 가정합니다.
이 태스크 정보
전송자 인증 주제 확인 메소드 유효성 검증 요구사항을 충족시키기 위해 메시지 레벨 보호와 함께 웹 서비스 보안 프로그래밍 인터페이스를 사용하여 SOAP 요청 메시지 및 SAML 토큰을 보호할 수 있습니다. 웹 서비스 클라이언트에서 프로그래밍 인터페이스를 사용하는 것은 정책 세트 및 바인딩 구성을 사용하는 것에 대한 대안적 접근법입니다.
자체 발행 SAML 토큰을 작성한 다음 웹 서비스 클라이언트에서 웹 서비스 요청 메시지로 SAML 토큰을 전송할 수 있습니다. 이 태스크에서 사용되는 웹 서비스 애플리케이션 클라이언트는 다운로드 가능한 JaxWSServicesSamples 샘플 애플리케이션에 포함되어 있는 수정된 버전의 클라이언트 코드입니다. 샘플의 코드 스니펫은 프로시저 섹션에 설명되어 있고 예제 섹션에서 완전하고 즉시 사용 가능한 웹 서비스 클라이언트 샘플이 제공됩니다.
이 제품은 전송자 인증 주제 확인 메소드를 포함하는 SAML 토큰을 요구하는 기본 정책 세트를 제공하지 않습니다. 전송자 인증 주제 확인을 포함하는 SAML 토큰을 요구하도록 웹 서비스 보안 정책을 작성하는 방법 및 사용자 정의 바인딩 구성을 작성하는 방법에 대해 자세히 알아보려면 SAML 전송자 인증 토큰에 대한 클라이언트 및 제공자 바인딩에 대해 읽어 보십시오. 정책 및 바인딩을 웹 서비스 제공자에 첨부해야 합니다. 이 태스크에서 설명하고 있는 코드 샘플에서는 웹 서비스 제공자 정책이 SAML 토큰 및 메시지 본문 둘 다 X.509 보안 토큰을 사용하여 디지털로 서명되도록 요구하는 것으로 가정합니다.
프로시저
결과
전송자 인증 확인 메소드로 자체 발행 SAML 토큰을 작성한 다음 JAX-WS 프로그래밍 모델 및 WSS API를 사용하여 웹 서비스 요청 메시지와 함께 이 토큰을 전송했습니다.
예
다음 코드 샘플은 자체 발행 SAML 전송자 인증 토큰을 작성하고 작성한 SAML 토큰을 웹 서비스 요청 메시지로 전송하는 완전하고 즉시 사용 가능한 웹 서비스 클라이언트 애플리케이션입니다. 이 샘플 코드는 이전에 설명한 프로시저 단계를 보여줍니다.
/**
* The following source code is sample code created by IBM Corporation.
* This sample code is provided to you solely for the purpose of assisting you in the
* use of the technology. The code is provided 'AS IS', without warranty or condition of
* any kind. IBM shall not be liable for any damages arising out of your use of the
* sample code, even if IBM has been advised of the possibility of such damages.
*/
package com.ibm.was.wssample.sei.cli;
import com.ibm.was.wssample.sei.echo.EchoService12PortProxy;
import com.ibm.was.wssample.sei.echo.EchoStringInput;
import com.ibm.websphere.wssecurity.callbackhandler.SAMLGenerateCallbackHandler;
import com.ibm.websphere.wssecurity.wssapi.WSSConsumingContext;
import com.ibm.websphere.wssecurity.wssapi.WSSFactory;
import com.ibm.websphere.wssecurity.wssapi.WSSGenerationContext;
import com.ibm.websphere.wssecurity.wssapi.WSSTimestamp;
import com.ibm.websphere.wssecurity.wssapi.token.SAMLToken;
import com.ibm.websphere.wssecurity.wssapi.token.SecurityToken;
import com.ibm.websphere.wssecurity.callbackhandler.X509ConsumeCallbackHandler;
import com.ibm.websphere.wssecurity.callbackhandler.X509GenerateCallbackHandler;
import com.ibm.websphere.wssecurity.wssapi.WSSException;
import com.ibm.websphere.wssecurity.wssapi.signature.WSSSignPart;
import com.ibm.websphere.wssecurity.wssapi.signature.WSSSignature;
import com.ibm.websphere.wssecurity.wssapi.verification.WSSVerification;
import com.ibm.websphere.wssecurity.wssapi.token.X509Token;
import com.ibm.wsspi.wssecurity.core.token.config.WSSConstants;
import com.ibm.wsspi.wssecurity.saml.config.SamlConstants;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.cert.CertStore;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.CollectionCertStoreParameters;
import java.security.cert.X509Certificate;
import java.util.HashSet;
import java.util.Set;
import java.util.HashMap;
import java.util.Map;
import javax.xml.ws.BindingProvider;
public class SampleSamlSVClient {
private String urlHost = "localhost";
private String urlPort = "9081";
private static final String CONTEXT_BASE = "/WSSampleSei/";
private static final String ECHO_CONTEXT12 = CONTEXT_BASE+"EchoService12";
private String message = "HELLO";
private String uriString = "http://" + urlHost + ":" + urlPort;
private String endpointURL = uriString + ECHO_CONTEXT12;
private String input = message;
/**
* main()
*
* see printusage() for command-line arguments
*
* @param args
*/
public static void main(String[] args) {
SampleSamlSVClient sample = new SampleSamlSVClient();
sample.CallService();
}
/**
* CallService Parms were already read. Now call the service proxy classes.
*
*/
void CallService() {
String response = "ERROR!:";
try {
System.setProperty("java.security.auth.login.config", "profile_root/properties/wsjaas.conf");
// Initialize WSSFactory object
WSSFactory factory = WSSFactory.getInstance();
// Initialize WSSGenerationContext
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
// Create SAMLToken
HashMap<Object, Object> map = new HashMap<Object, Object>();
map.put(SamlConstants.CONFIRMATION_METHOD, "sender-vouches");
map.put(SamlConstants.TOKEN_TYPE, WSSConstants.SAML.SAML20_VALUE_TYPE);
map.put(SamlConstants.SAML_NAME_IDENTIFIER, "Alice");
map.put(SamlConstants.SIGNATURE_REQUIRED, "true");
SAMLGenerateCallbackHandler callbackHandler = new SAMLGenerateCallbackHandler(map);
SecurityToken samlToken = factory.newSecurityToken(SAMLToken.class, callbackHandler, "system.wss.generate.saml");
System.out.println("SAMLToken id = " + samlToken.getId());
// Initialize web services client.
EchoService12PortProxy echo = new EchoService12PortProxy();
echo._getDescriptor().setEndpoint(endpointURL);
// Configure SOAPAction properties
BindingProvider bp = (BindingProvider) (echo._getDescriptor().getProxy());
Map<String, Object> requestContext = bp.getRequestContext();
requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpointURL);
requestContext.put(BindingProvider.SOAPACTION_USE_PROPERTY, Boolean.TRUE);
requestContext.put(BindingProvider.SOAPACTION_URI_PROPERTY, "echoOperation");
// Initialize WSSGenerationContext
WSSGenerationContext gencont = factory.newWSSGenerationContext();
gencont.add(samlToken);
// Add X.509 Tokens for message protection
X509GenerateCallbackHandler x509callbackHandler = new X509GenerateCallbackHandler(
null,
"profile_root/etc/ws-security/samples/dsig-sender.ks",
"JKS",
"client".toCharArray(),
"soaprequester",
"client".toCharArray(),
"CN=SOAPRequester, OU=TRL, O=IBM, ST=Kanagawa, C=JP", null);
SecurityToken x509 = factory.newSecurityToken(X509Token.class,
x509callbackHandler, "system.wss.generate.x509");
WSSSignature sig = factory.newWSSSignature(x509);
sig.setSignatureMethod(WSSSignature.RSA_SHA1);
WSSSignPart sigPart = factory.newWSSSignPart();
sigPart.setSignPart(samlToken);
sigPart.addTransform(WSSSignPart.TRANSFORM_STRT10);
sig.addSignPart(sigPart);
sig.addSignPart(WSSSignature.BODY);
// Add timestamp
WSSTimestamp timestamp = factory.newWSSTimestamp();
gencont.add(timestamp);
sig.addSignPart(WSSSignature.TIMESTAMP);
gencont.add(sig);
WSSConsumingContext concont = factory.newWSSConsumingContext();
// Prepare to consume timestamp in response message
concont.add(WSSConsumingContext.TIMESTAMP);
// Prepare to verify digital signature in response message
X509Certificate x509cert = null;
try {
InputStream is = new FileInputStream("profile_root/etc/ws-security/samples/intca2.cer");
CertificateFactory cf = CertificateFactory.getInstance("X.509");
x509cert = (X509Certificate) cf.generateCertificate(is);
} catch (FileNotFoundException e1) {
throw new WSSException(e1);
} catch (CertificateException e2) {
throw new WSSException(e2);
}
Set<Object> eeCerts = new HashSet<Object>();
eeCerts.add(x509cert);
java.util.List<CertStore> certList = new java.util.ArrayList<CertStore>();
CollectionCertStoreParameters certparam = new CollectionCertStoreParameters(eeCerts);
CertStore cert = null;
try {
cert = CertStore.getInstance("Collection", certparam, "IBMCertPath");
} catch (NoSuchProviderException e1) {
throw new WSSException(e1);
} catch (InvalidAlgorithmParameterException e2) {
throw new WSSException(e2);
} catch (NoSuchAlgorithmException e3) {
throw new WSSException(e3);
}
if (certList != null) {
certList.add(cert);
}
X509ConsumeCallbackHandler callbackHandlerVer = new X509ConsumeCallbackHandler(
"profile_root/etc/ws-security/samples/dsig-receiver.ks",
"JKS",
"server".toCharArray(),
certList,
java.security.Security.getProvider("IBMCertPath"));
WSSVerification ver = factory.newWSSVerification(X509Token.class, callbackHandlerVer);
ver.addRequiredVerifyPart(WSSVerification.BODY);
concont.add(ver);
gencont.process(requestContext);
concont.process(requestContext);
// Build the input object
EchoStringInput echoParm =
new com.ibm.was.wssample.sei.echo.ObjectFactory().createEchoStringInput();
echoParm.setEchoInput(input);
System.out.println(">> CLIENT: SEI Echo to " + endpointURL);
// Call the service
response = echo.echoOperation(echoParm).getEchoResponse();
System.out.println(">> CLIENT: SEI Echo invocation complete.");
System.out.println(">> CLIENT: SEI Echo response is: " + response);
} catch (Exception e) {
System.out.println(">> CLIENT: ERROR: SEI Echo EXCEPTION.");
e.printStackTrace();
}
}
}
SAMLToken id = _6CDDF0DBF91C044D211271166233407
Retrieving document at 'file:profile_root/.../wsdl/'.
>> CLIENT: SEI Echo to http://localhost:9080/WSSampleSei/EchoService12
>> CLIENT: SEI Echo invocation complete.
>> CLIENT: SEI Echo response is: SOAP12==>>HELLO