1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.opensaml.saml1.binding.encoding;
18
19 import java.io.IOException;
20 import java.io.OutputStreamWriter;
21 import java.io.UnsupportedEncodingException;
22 import java.io.Writer;
23
24 import org.opensaml.Configuration;
25 import org.opensaml.common.SAMLObject;
26 import org.opensaml.common.binding.SAMLMessageContext;
27 import org.opensaml.common.xml.SAMLConstants;
28 import org.opensaml.ws.message.MessageContext;
29 import org.opensaml.ws.message.encoder.MessageEncodingException;
30 import org.opensaml.ws.soap.common.SOAPObjectBuilder;
31 import org.opensaml.ws.soap.soap11.Body;
32 import org.opensaml.ws.soap.soap11.Envelope;
33 import org.opensaml.ws.transport.http.HTTPOutTransport;
34 import org.opensaml.ws.transport.http.HTTPTransportUtils;
35 import org.opensaml.xml.XMLObjectBuilderFactory;
36 import org.opensaml.xml.util.XMLHelper;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39 import org.w3c.dom.Element;
40
41
42
43
44 public class HTTPSOAP11Encoder extends BaseSAML1MessageEncoder {
45
46
47 private final Logger log = LoggerFactory.getLogger(HTTPSOAP11Encoder.class);
48
49
50 public HTTPSOAP11Encoder() {
51 super();
52 }
53
54
55 public String getBindingURI() {
56 return SAMLConstants.SAML1_SOAP11_BINDING_URI;
57 }
58
59
60 public boolean providesMessageConfidentiality(MessageContext messageContext) throws MessageEncodingException {
61 if (messageContext.getOutboundMessageTransport().isConfidential()) {
62 return true;
63 }
64
65 return false;
66 }
67
68
69 public boolean providesMessageIntegrity(MessageContext messageContext) throws MessageEncodingException {
70 if (messageContext.getOutboundMessageTransport().isIntegrityProtected()) {
71 return true;
72 }
73
74 return false;
75 }
76
77
78 protected void doEncode(MessageContext messageContext) throws MessageEncodingException {
79 validateMessageContent(messageContext);
80 SAMLMessageContext samlMsgCtx = (SAMLMessageContext) messageContext;
81
82 SAMLObject samlMessage = samlMsgCtx.getOutboundSAMLMessage();
83 if (samlMessage == null) {
84 throw new MessageEncodingException("No outbound SAML message contained in message context");
85 }
86
87 signMessage(samlMsgCtx);
88 Envelope envelope = buildSOAPMessage(samlMessage);
89 samlMsgCtx.setOutboundMessage(envelope);
90
91 Element envelopeElem = marshallMessage(envelope);
92 try {
93 HTTPOutTransport outTransport = (HTTPOutTransport) messageContext.getOutboundMessageTransport();
94 HTTPTransportUtils.addNoCacheHeaders(outTransport);
95 HTTPTransportUtils.setUTF8Encoding(outTransport);
96 HTTPTransportUtils.setContentType(outTransport, "text/xml");
97 outTransport.setHeader("SOAPAction", "http://www.oasis-open.org/committees/security");
98
99 Writer out = new OutputStreamWriter(outTransport.getOutgoingStream(), "UTF-8");
100 XMLHelper.writeNode(envelopeElem, out);
101 out.flush();
102 } catch (UnsupportedEncodingException e) {
103 log.error("JVM does not support required UTF-8 encoding");
104 throw new MessageEncodingException("JVM does not support required UTF-8 encoding");
105 } catch (IOException e) {
106 log.error("Unable to write message content to outbound stream", e);
107 throw new MessageEncodingException("Unable to write message content to outbound stream", e);
108 }
109 }
110
111
112
113
114
115
116
117
118 @SuppressWarnings("unchecked")
119 protected Envelope buildSOAPMessage(SAMLObject samlMessage) {
120 log.debug("Building SOAP message");
121 XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory();
122
123 SOAPObjectBuilder<Envelope> envBuilder = (SOAPObjectBuilder<Envelope>) builderFactory
124 .getBuilder(Envelope.DEFAULT_ELEMENT_NAME);
125 Envelope envelope = envBuilder.buildObject();
126
127 log.debug("Adding SAML message to the SOAP message's body");
128 SOAPObjectBuilder<Body> bodyBuilder = (SOAPObjectBuilder<Body>) builderFactory
129 .getBuilder(Body.DEFAULT_ELEMENT_NAME);
130 Body body = bodyBuilder.buildObject();
131 body.getUnknownXMLObjects().add(samlMessage);
132 envelope.setBody(body);
133
134 return envelope;
135 }
136
137
138
139
140
141
142
143
144 protected void validateMessageContent(MessageContext messageContext) throws MessageEncodingException {
145 if (!(messageContext instanceof SAMLMessageContext)) {
146 log.error("Invalid message context type, this encoder only support SAMLMessageContext");
147 throw new MessageEncodingException(
148 "Invalid message context type, this encoder only support SAMLMessageContext");
149 }
150
151 if (!(messageContext.getOutboundMessageTransport() instanceof HTTPOutTransport)) {
152 log.error("Invalid outbound message transport type, this encoder only support HTTPOutTransport");
153 throw new MessageEncodingException(
154 "Invalid outbound message transport type, this encoder only support HTTPOutTransport");
155 }
156 }
157 }