API de WS-Trust Client
La API (interfaz de programación de aplicaciones) de WS-Trust Client incluye la clase WSSTrustClient, la clase WSSTrustClientValidateResult y otras clases de programas de utilidad de configuración. La clase WSSTrustClient proporciona funciones de ayudante que envían solicitudes SOAP de WS-Trust al STS (Security Token Service) externo que se ha especificado, por lo que el STS puede emitir o validar una o varias aserciones SAML y otros tipos de señales de seguridad.
Visión general
WebSphere Application Server incluyen la función de WS-Trust Client , implementada mediante la clase WSSTrustClient, que envía solicitudes SOAP de WS-Trust a un STS (Security Token Service) externo especificado. Mediante las solicitudes de confianza, el STS puede emitir una o más aserciones SAML u otros tipos de señales de seguridad. La clase WSSTrustClient da soporte a la especificación de la versión 1.3 de OASIS WS-Trust y también a la especificación de la versión 1.2 de WS-Trust. Además, la función admite las especificaciones de la versión 1.1 de SOAP y la versión 1.2 de SOAP.
El código de ejemplo siguiente muestra la forma en la que un cliente de servicios web utiliza la API WSSTrustClient para solicitar una señal de titularidad SAML. En el texto explicativo que precede al ejemplo de código, el término Señal SAML se utiliza de forma intercambiable con el término Aserción SAML.
La clase WSSTrustClient
Puede copiar el código de ejemplo en una aplicación de herramienta de ensamblaje, como Rational Application Developer (RAD), y empezar a utilizar el código tras llevar a cabo los pasos de configuración. Utilice la clase WSSTrustClient, junto con otras API de SAML, para crear funciones útiles de SAML. Consulte el Javadoc de la API de SAML para obtener más información.
La clase WSSTrustClient es una clase abstracta y tiene dos implementaciones concretas: una implementación de la versión 1.3 de WS-Trust y una implementación de la versión 1.2 de WS-Trust. En la línea 50 del ejemplo de código, el código de cliente de servicios web SAMLWSTrustClientExample invoca el método WSSTrustClient.getInstance(ProviderConfig) para recuperar la implementación de WS-Trust v1.3. El método getInstance() toma un objeto ProviderConfig único, que especifica los datos de configuración que son relevantes para el emisor de señal SAML. También se crea una instancia de un objeto ProviderConfig en el código de ejemplo en la línea 32. El código de cliente envía mensajes de solicitud de la versión 1.3 de WS-Trust a un punto final STS de destino. En el ejemplo, el punto final es https://MyCompany/Trust/13/UsernameMixed. Para utilizar el código de ejemplo, sustituya este punto final STS de ejemplo por el punto final STS específico que tenga pensado utilizar.
El soporte de SAML de la API de WSS complementa las interfaces com.ibm.websphere.wssecurity.wssapi.token.SAMLTokenFactory y com.ibm.websphere.wssecurity.wssapi.trust.WSSTrustClient. Las interfaces de programación SAMLTokenFactory y WSSTrustClient procesan las SAMLTokens que se generan mediante el método com.ibm.websphere.wssecurity.wssapi.WSSFactory newSecurityToken(). A la inversa, las SAMLTokens que se generan mediante SAMLTokenFactory o que se devuelven de WSSTrustClient pueden utilizarse en la API de WSS. La determinación de qué API utilizar en la aplicación depende de sus necesidades específicas. El soporte SAML de la API de WSS es completo en el sentido de que proporciona funcionalidad equivalente a la de las interfaces SAMLTokenFactory y WSSTrustClient en lo que respecta a las aplicaciones cliente de servicios web. La interfaz SAMLTokenFactory tiene funciones adicionales para validar las SAMLTokens y para crear el asunto JAAS que representa las SAMLTokens autenticadas. Esta validación es útil en el proveedor de servicios web. Al desarrollar aplicaciones para consumir SAMLTokens, la interfaz de programación de SAMLTokenFactory es más adecuada para usted.
Ejemplo: código de cliente de servicios web que utiliza la clase WSSTrustClient
1. package sample;
2.
3.
import com.ibm.websphere.wssecurity.wssapi.WSSException;
4. import com.ibm.websphere.wssecurity.wssapi.token.SecurityToken;
5.
import com.ibm.websphere.wssecurity.wssapi.trust.WSSTrustClient;
6. import com.ibm.websphere.wssecurity.wssapi.token.SAMLToken;
7. import com.ibm.websphere.wssecurity.wssapi.XMLStructure;
8.
9.
10. import com.ibm.wsspi.wssecurity.core.token.config.RequesterConfiguration;
11. import com.ibm.wsspi.wssecurity.core.token.config.WSSConstants.Namespace;
12. import com.ibm.wsspi.wssecurity.core.token.config.WSSConstants.TokenType;
13. import com.ibm.wsspi.wssecurity.core.token.config.WSSConstants.WST13;
14. import com.ibm.wsspi.wssecurity.trust.config.ProviderConfig;
15. import com.ibm.wsspi.wssecurity.trust.config.RequesterConfig;
16. import com.ibm.wsspi.wssecurity.wssapi.OMStructure;
17.
18. import org.apache.axiom.om.OMElement;
19. import org.apache.axis2.util.XMLPrettyPrinter;
20.
21. import java.util.List;
22. import java.io.ByteArrayOutputStream;
23. import java.io.InputStream;
24. import java.io.BufferedReader;
25. import java.io.InputStreamReader;
26. import java.io.IOException;
27.
28. public class WSSTrustClientExample {
29.
30. public static void main(String[] args) {
31. try {
32. ProviderConfig providerConfig = WSSTrustClient.newProviderConfig(Namespace.WST13, https://MyCompany.com/Trust/13/UsernameMixed );
33. 34. showProviderConfigDefaultValue(providerConfig);
35. 36. providerConfig.setPolicySetName("Username WSHTTPS default");
37. providerConfig.setBindingName("SamlTCSample");
38. providerConfig.setBindingScope("domain");
39.
40.
41. RequesterConfig requesterConfig = WSSTrustClient.newRequesterConfig(Namespace.WST13);
42. 43. showRequestConfigDefaultValue(requesterConfig);
44. 45. requesterConfig.put(RequesterConfiguration.RSTT.APPLIESTO_ADDRESS, "https://user.MyCompany:9443/WSSampleSei/EchoService12");
46. requesterConfig.put(RequesterConfiguration.RSTT.TOKENTYPE, TokenType.SAML11);
47. requesterConfig.put(RequesterConfiguration.RSTT.KEYTYPE, WST13.KEYTYPE_BEARER);
48. requesterConfig.setSOAPNamespace(Namespace.SOAP12);
49. 50. WSSTrustClient client = WSSTrustClient.getInstance(providerConfig);
51. List<SecurityToken> securityTokens = client.issue(providerConfig, requesterConfig);
52. 53. // Process SAML token
54. if (securityTokens != null && !securityTokens.isEmpty()) {
55. System.out.println("Number of tokens returned = " + securityTokens.size());
56. SecurityToken token = securityTokens.get(0);
57. if (token instanceof SAMLToken) {
58. showSAMLToken((SAMLToken)token);
59. } else {
60. System.out.println("Returned token is not an SAMLToken");
61. }
62. } else {
63. System.out.println("No securityToken obtained.");
64. }
65. 66. } catch (SoapSecurityException ex) {
67. System.out.println("Caught exception: " + ex.getMessage());
68. ex.printStackTrace();
69. }
70. }
71.
72. private static void showProviderConfigDefaultValue(ProviderConfig providerConfig) {
73. System.out.println("providerConfig.getApplicationName() = " + providerConfig.getApplicationName());
74. System.out.println("providerConfig.getBindingName() = " + providerConfig.getBindingName());
75. System.out.println("ProviderConfig.getBindingScope() = " + providerConfig.getBindingScope());
76. System.out.println("providerConfig.getIssuerURI() = " + providerConfig.getIssuerURI());
77.
78. System.out.println("providerConfig.getPolicySetName() = " + providerConfig.getPolicySetName());
79. System.out.println("ProviderConfig.getPortName() = " + providerConfig.getPortName());
80. System.out.println("providerConfig.getProvider() = " + providerConfig.getProvider());
81. System.out.println("ProviderConfig.getServiceName() = " + providerConfig.getServiceName());
82. System.out.println("providerConfig.getWSTrustNamespace() = " + providerConfig.getWSTrustNamespace());
83. System.out.println("ProviderConfig.toString() = " + providerConfig.toString());
84. }
85. 86. private static void showRequestConfigDefaultValue(RequesterConfig requesterConfig) {
87. System.out.println("requesterConfig.getRSTTProperties() = " + requesterConfig.getRSTTProperties());
88. System.out.println("requesterConfig.getSecondaryParameters() = " + requesterConfig.getSecondaryParameters());
89. System.out.println("requesterConfig.getSOAPNamespace() = " + requesterConfig.getSOAPNamespace());
90. System.out.println("requesterConfig.getWSAddressingNamespace() = " + requesterConfig.getWSAddressingNamespace());
91. 92. System.out.println("requesterConfig.getMessageID() = " + requesterConfig.getMessageID());
93. System.out.println("requesterConfig.toString() = " + requesterConfig.toString());
94. }
95. 96. private static void showSAMLToken(SAMLToken samlToken){
97. System.out.println("samlToken.getAssertionQName() = " + samlToken.getAssertionQName());
98. System.out.println("samlToken.getAudienceRestriction() = " + samlToken.getAudienceRestriction());
99. System.out.println("samlToken.getAuthenticationMethod() = " + samlToken.getAuthenticationMethod());
100. System.out.println("samlToken.getConfirmationMethod() = " + samlToken.getConfirmationMethod());
101. System.out.println("samlToken.getId() = " + samlToken.getId());
102. System.out.println("samlToken.getKeyIdentifier() = " + samlToken.getKeyIdentifier());
103. System.out.println("samlToken.getKeyIdentifierEncodingType() = " + samlToken.getKeyIdentifierEncodingType());
104. System.out.println("samlToken.getKeyIdentifierValueType() = " + samlToken.getKeyIdentifierValueType());
105. System.out.println("samlToken.getKeyName() = " + samlToken.getKeyName());
106. System.out.println("samlToken.getPrincipal() = " + samlToken.getPrincipal());
107. System.out.println("samlToken.getProperties() = " + samlToken.getProperties());
108. System.out.println("samlToken.getReferenceURI() = " + samlToken.getReferenceURI());
109. System.out.println("samlToken.getSAMLAttributes() = " + samlToken.getSAMLAttributes());
110. System.out.println("samlToken.getSamlCreated() = " + samlToken.getSamlCreated());
111. System.out.println("samlToken.getSamlExpires() = " + samlToken.getSamlExpires());
112. System.out.println("samlToken.getSamlID() = " + samlToken.getSamlID());
113. System.out.println("samlToken.getSAMLIssuerName() = " + samlToken.getSAMLIssuerName());
114. System.out.println("samlToken.getSAMLNameID() = " + samlToken.getSAMLNameID());
115. System.out.println("samlToken.getStringAttributes() = " + samlToken.getStringAttributes());
116. System.out.println("samlToken.getSubjectDNS() = " + samlToken.getSubjectDNS());
117. System.out.println("samlToken.getSubjectIPAddress() = " + samlToken.getSubjectIPAddress());
118. System.out.println("samlToken.getThumbprint() = " + samlToken.getThumbprint());
119. System.out.println("samlToken.getThumbprintEncodingType() = " + samlToken.getThumbprintEncodingType());
120. System.out.println("samlToken.getThumbprintValueType() = " + samlToken.getThumbprintValueType());
121. System.out.println("samlToken.getTokenQname() = " + samlToken.getTokenQname());
122. System.out.println("samlToken.getValueType() = " + samlToken.getValueType());
123. 124. XMLStructure samlXmlStructure = samlToken.getXML();
125. if (samlXmlStructure != null && samlXmlStructure instanceof OMStructure) {
126. OMStructure samlOMStructure = (OMStructure) samlXmlStructure;
127. System.out.println("((OMStructure)samlToken.getXML()).getNode()formatted = " + formatXML(samlOMStructure.getNode()));
128. }
129. 130. try {
131. InputStream is = samlToken.getXMLInputStream();
132. if (is != null) {
133. try {
134. BufferedReader reader = new BufferedReader(new InputStreamReader(is));
135. StringBuilder sb = new StringBuilder();
136. String line = null;
137. while ((line = reader.readLine()) != null) {
138. sb.append(line + "\n");
139. }
140. System.out.println(sb.toString());
141. } catch (Exception ex) {
142. System.out.println("Caught exception reading from InputStream: " + ex.getMessage());
143. ex.printStackTrace();
144. } finally {
145. try {
146. is.close();
147. } catch (IOException e) {
148. e.printStackTrace();
149. }
150. }
151. }
152. } catch (WSSException wex) {
153. System.out.println("Caught exception getXMLInputStream(): " + wex.getMessage());
154. wex.printStackTrace();
155. }
156. }
157. 158. private static String formatXML(OMElement omInput) {
159. ByteArrayOutputStream out = new ByteArrayOutputStream();
160. String output = "";
161.
162. try {
163. XMLPrettyPrinter.prettify(omInput, out);
164. output = out.toString();
165. } catch (Throwable e) {
166. try {
167. output = omInput.toString();
168. } catch (Throwable e2) {
169. System.out.println("Caught exception: " + e2.getMessage());
170. e2.printStackTrace();
171. }
172. }
173. return output;
174. }
175.
176. }
Soporte de la clase WSSTrustClient para conjuntos de política y enlaces
La función de WS-Trust Client da soporte a enlaces específicos de aplicación y a enlaces generales para su uso con el conjunto de políticas de cliente de confianza y los documentos de enlace. Además, los enlaces generales y los enlaces predeterminados reciben soporte si la aplicación se ejecuta en el entorno del servidor de aplicaciones. Los enlaces generales son compatibles en el entorno de cliente ligero, pero los enlaces predeterminados no.
La gestión del conjunto de políticas y enlaces de la API de cliente de WS-Trust es similar a la gestión de un conjunto de políticas y enlaces para un cliente de servicios web. No obstante, existen diferencias que son únicas de WS-Trust Client. Una diferencia es que WS-Trust Client no utiliza conexiones del conjunto de políticas. En su lugar, el nombre del conjunto de políticas y el nombre de enlaces se especifican en un objeto ProviderConfig, tal como se muestra en la línea 36 y en la línea 37 del código de ejemplo.
Cuando el cliente WS-Trust busca enlaces, la forma en la que el cliente gestiona el ámbito de búsqueda difiere de la del cliente de servicios web. Si no especifica la propiedad wstrustClientBindingScope para el enlace de cliente de confianza, el sistema busca primero en la aplicación un enlace específico de la aplicación con el nombre de enlace que ha especificado. Si se encuentra el enlace, se utiliza para la solicitud de cliente de confianza. Si no se encuentra ningún enlace específico de la aplicación, el sistema busca en los enlaces generales disponibles un enlace con el nombre que ha especificado. Si se encuentra un enlace general, se utiliza para la solicitud de cliente de confianza. Si no se encuentra ningún enlace con el nombre específico se utilizarán los enlaces predeterminados en un entorno de servidor. Los enlaces predeterminados solamente se utilizan en un entorno de servidor. Si se especifica el ámbito de enlace, sólo se utilizará dicho ámbito para búsqueda de enlaces.
La línea 38 del código de ejemplo, providerConfig.setBindingScope("domain"), indica que el ejemplo utiliza enlaces generales. También puede establecer el ámbito de enlace en application para indicar que el código de ejemplo utiliza enlaces específicos de la aplicación. El ejemplo utiliza el enlace general denominado SamlTCSample. Los enlaces específicos de aplicación y generales reciben soporte en el servidor de aplicaciones y en el entorno de cliente ligero. Para obtener más información sobre la configuración de enlaces SamlTCSample cuando se instala la aplicación en el servidor de aplicaciones, lea el apartado sobre la configuración de conjuntos de política y enlaces para comunicarse con STS.
El código showProviderConfigDefaultValue(providerConfig) de la línea 34 del código de ejemplo muestra los valores predeterminados. El código de ejemplo incluye un método de utilidad que imprime el contenido de providerConfig.
La línea 51 del código de ejemplo, List<SecurityToken> securityTokens = client.issue(providerConfig, requesterConfig), envía una solicitud de problema WS-Trust. El segundo parámetro de esta línea especifica el objeto RequesterConfig, y este parámetro determina el contenido de la solicitud de emisión. El código de la línea 41, RequesterConfig requesterConfig = WSSTrustClient.newRequesterConfig(Namespace.WST13), crea una instancia de un objeto RequesterConfig que se utiliza para construir la solicitud de confianza utilizando el espacio de nombre de la versión 1.3 de WS-Trust. En la línea 43 se muestra una función de programa de utilidad: showRequestConfigDefaultValue(requesterConfig). Esta función muestra los valores predeterminados del objeto RequesterConfig. El código entre las líneas 45 y 48 inicializa RequesterConfig para solicitar la señal de titularidad SAML de la versión 1.1. Esta señal se utiliza para acceder al punto final de servicio mediante el espacio de nombres SOAP 1.2. En el ejemplo, el punto final de servicio es https://user.MyCompany.com:9443/WSSampleSei/EchoService12.
Soporte de argumentos JVM
Antes de ejecutar el código de ejemplo, debe configurar varios argumentos de Java™ Virtual Machine (JVM). El código de ejemplo implementa el conjunto de políticas predeterminado Username WSHTTPS, que tiene dos requisitos: 1) una señal Username se envía al STS; y 2) los mensajes se protegen utilizando la capa de sockets segura (SSL). Para configurar el entorno para que cumpla estos requisitos, configure primero el archivo ssl.client.props para definir un almacén de confianza. Para obtener instrucciones paso a paso, consulte la información sobre la ejecución de un cliente JAX-WS de servicios web no gestionado.
Para satisfacer el segundo requisito sobre la protección de mensajes SSL, obtenga una copia del certificado STS SSL X.509 e insértelo en el almacén de confianza. Para ello, siga los pasos del tema sobre la utilización del mandato retrieveSigners en SSL para habilitar la confianza de servidor a servidor. Como alternativa, puede aceptar el certificado STS cuando envíe la primera solicitud de confianza al STS si la propiedad com.ibm.ssl.enableSignerExchangePrompt del archivo profile_home/properties/ssl.client.props se establece en true. Para obtener más información acerca de esta opción, consulte la información sobre cómo cambiar solicitud de intercambio automático del firmante en el cliente.
Además, debe especificar el archivo de configuración JAAS del cliente de forma que el entorno de ejecución del cliente pueda localizar la configuración de inicio de sesión JAAS de la señal de nombre de usuario LoginModule. Especifique el parámetro utilizando este código: -Djava.security.auth.login.config="%WAS_HOME%\properties\wsjaas_client.conf. En la vía de acceso de clases también debe incluir el archivo jar de cliente ligero, por ejemplo, com.ibm.jaxws.thinclient_9.0.jar. Para obtener más información, consulte sobre la ejecución de una aplicación cliente JAX-WS de servicios web no gestionados.
Ejecución de código de ejemplo
Un requisito previo para ejecutar el código de ejemplo es configurar un punto final de STS externo para emitir una señal de titularidad SAML 1.1. para los servicios web especificados tal como define la propiedad RequesterConfiguration.RSTT.APPLIESTO_ADDRESS.
177. <?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
178. <soapenv:Header>
179. <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">https://user.MyCompany.com/Trust/13/UsernameMixed</wsa:To>
180. <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">urn:uuid:4951B6775950CAC92A1252458259166</wsa:MessageID>
181. <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue</wsa:Action>
182. </soapenv:Header>
183. <soapenv:Body>
184. <wst:RequestSecurityToken xmlns:wst="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
185. <wst:TokenType>http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1</wst:TokenType>
186. <wst:RequestType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue</wst:RequestType>
187. <wst:KeyType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/Bearer</wst:KeyType>
188. <wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
189. <wsa:EndpointReference xmlns:wsa="http://www.w3.org/2005/08/addressing">
190. <wsa:Address>https://user.MyCompany.com:9443/WSSampleSei/EchoService12</wsa:Address>
191. </wsa:EndpointReference>
192. </wsp:AppliesTo>
193. </wst:RequestSecurityToken>
194. </soapenv:Body>
195. </soapenv:Envelope>
- -DtraceSettingsFile=MyTraceSettings.properties
- -Djava.util.logging.manager=com.ibm.ws.bootstrap.WsLogManager
- -Djava.util.logging.configureByServer=true
Devolución de la señal SAML
196. <?xml version="1.0" encoding="UTF-8"?>
197. <saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" MajorVersion="1" MinorVersion="1"
198. AssertionID="_f7f65d28-fbb1-4e10-8ddf-f4b6ed0c8277" Issuer="http://MyCompany.com/Trust"
199. IssueInstant="2009-09-09T01:04:41.144Z">
200. <saml:Conditions NotBefore="2009-09-09T01:04:41.141Z" NotOnOrAfter="2009-09-09T11:04:41.141Z">
201. <saml:AudienceRestrictionCondition>
202. <saml:Audience>https://user.MyCompany.com:9443/WSSampleSei/EchoService12</saml:Audience>
203. </saml:AudienceRestrictionCondition>
204. </saml:Conditions>
205. <saml:AuthenticationStatement AuthenticationMethod="urn:oasis:names:tc:SAML:1.0:am:password"
206. AuthenticationInstant="2009-09-09T01:04:41.131Z">
207. <saml:Subject>
208. <saml:SubjectConfirmation>
209. <saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:bearer</saml:ConfirmationMethod>
210. </saml:SubjectConfirmation>
211. </saml:Subject>
212. </saml:AuthenticationStatement>
213. <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
214. <ds:SignedInfo>
215. <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
216. <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
217. <ds:Reference URI="#_f7f65d28-fbb1-4e10-8ddf-f4b6ed0c8277">
218. <ds:Transforms>
219. <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
220. <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
221. </ds:Transforms>
222. <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
223. <ds:DigestValue>AQ6e7YQqKgcg/B/ebBj8/DF+uWg=</ds:DigestValue>
224. </ds:Reference>
225. </ds:SignedInfo>
226. <ds:SignatureValue>SuccIOniR . . . . yjTh9iQs=</ds:SignatureValue>
227. <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
228. <X509Data>
229. <X509Certificate>MIIB3zCCAUi . . . . itzymqg3</X509Certificate>
230. </X509Data>
231. </KeyInfo>
232. </ds:Signature>
233. </saml:Assertion>