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.OutputStream;
20 import java.io.OutputStreamWriter;
21 import java.io.UnsupportedEncodingException;
22 import java.io.Writer;
23
24 import org.apache.velocity.VelocityContext;
25 import org.apache.velocity.app.VelocityEngine;
26 import org.opensaml.common.SAMLObject;
27 import org.opensaml.common.binding.SAMLMessageContext;
28 import org.opensaml.common.xml.SAMLConstants;
29 import org.opensaml.saml1.core.ResponseAbstractType;
30 import org.opensaml.ws.message.MessageContext;
31 import org.opensaml.ws.message.encoder.MessageEncodingException;
32 import org.opensaml.ws.transport.http.HTTPOutTransport;
33 import org.opensaml.ws.transport.http.HTTPTransportUtils;
34 import org.opensaml.xml.util.Base64;
35 import org.opensaml.xml.util.XMLHelper;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39
40
41
42 public class HTTPPostEncoder extends BaseSAML1MessageEncoder {
43
44
45 private final Logger log = LoggerFactory.getLogger(HTTPPostEncoder.class);
46
47
48 private VelocityEngine velocityEngine;
49
50
51 private String velocityTemplateId;
52
53
54
55
56
57
58
59 public HTTPPostEncoder(VelocityEngine engine, String templateId) {
60 super();
61 velocityEngine = engine;
62 velocityTemplateId = templateId;
63 }
64
65
66 public String getBindingURI() {
67 return SAMLConstants.SAML1_POST_BINDING_URI;
68 }
69
70
71 public boolean providesMessageConfidentiality(MessageContext messageContext) throws MessageEncodingException {
72 return false;
73 }
74
75
76 public boolean providesMessageIntegrity(MessageContext messageContext) throws MessageEncodingException {
77 return false;
78 }
79
80
81 protected void doEncode(MessageContext messageContext) throws MessageEncodingException {
82 if (!(messageContext instanceof SAMLMessageContext)) {
83 log.error("Invalid message context type, this encoder only support SAMLMessageContext");
84 throw new MessageEncodingException(
85 "Invalid message context type, this encoder only support SAMLMessageContext");
86 }
87
88 if (!(messageContext.getOutboundMessageTransport() instanceof HTTPOutTransport)) {
89 log.error("Invalid outbound message transport type, this encoder only support HTTPOutTransport");
90 throw new MessageEncodingException(
91 "Invalid outbound message transport type, this encoder only support HTTPOutTransport");
92 }
93
94 SAMLMessageContext samlMsgCtx = (SAMLMessageContext) messageContext;
95
96 SAMLObject outboundMessage = samlMsgCtx.getOutboundSAMLMessage();
97 if (outboundMessage == null) {
98 throw new MessageEncodingException("No outbound SAML message contained in message context");
99 }
100 String endpointURL = getEndpointURL(samlMsgCtx).buildURL();
101
102 if (samlMsgCtx.getOutboundSAMLMessage() instanceof ResponseAbstractType) {
103 ((ResponseAbstractType) samlMsgCtx.getOutboundSAMLMessage()).setRecipient(endpointURL);
104 }
105
106 signMessage(samlMsgCtx);
107 samlMsgCtx.setOutboundMessage(outboundMessage);
108
109 postEncode(samlMsgCtx, endpointURL);
110 }
111
112
113
114
115
116
117
118
119
120 protected void postEncode(SAMLMessageContext messageContext, String endpointURL) throws MessageEncodingException {
121 log.debug("Invoking velocity template to create POST body");
122
123 try {
124 VelocityContext context = new VelocityContext();
125
126 log.debug("Encoding action url of: {}", endpointURL);
127 context.put("action", endpointURL);
128
129 log.debug("Marshalling and Base64 encoding SAML message");
130 String messageXML = XMLHelper.nodeToString(marshallMessage(messageContext.getOutboundSAMLMessage()));
131 String encodedMessage = Base64.encodeBytes(messageXML.getBytes("UTF-8"), Base64.DONT_BREAK_LINES);
132 context.put("SAMLResponse", encodedMessage);
133
134 if (messageContext.getRelayState() != null) {
135 log.debug("Setting TARGET parameter to: {}", messageContext.getRelayState());
136 context.put("TARGET", messageContext.getRelayState());
137 }
138
139 HTTPOutTransport outTransport = (HTTPOutTransport) messageContext.getOutboundMessageTransport();
140 HTTPTransportUtils.addNoCacheHeaders(outTransport);
141 HTTPTransportUtils.setUTF8Encoding(outTransport);
142 HTTPTransportUtils.setContentType(outTransport, "text/html");
143
144 OutputStream transportOutStream = outTransport.getOutgoingStream();
145 Writer out = new OutputStreamWriter(transportOutStream, "UTF-8");
146 velocityEngine.mergeTemplate(velocityTemplateId, "UTF-8", context, out);
147 out.flush();
148 }catch(UnsupportedEncodingException e){
149 log.error("UTF-8 encoding is not supported, this VM is not Java compliant.");
150 throw new MessageEncodingException("Unable to encode message, UTF-8 encoding is not supported");
151 } catch (Exception e) {
152 log.error("Error invoking velocity template", e);
153 throw new MessageEncodingException("Error creating output document", e);
154 }
155 }
156 }