📄 samlsoapbinding.java
字号:
/* * The OpenSAML License, Version 1. * Copyright (c) 2002 * University Corporation for Advanced Internet Development, Inc. * All rights reserved * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution, if any, must include * the following acknowledgment: "This product includes software developed by * the University Corporation for Advanced Internet Development * <http://www.ucaid.edu>Internet2 Project. Alternately, this acknowledegement * may appear in the software itself, if and wherever such third-party * acknowledgments normally appear. * * Neither the name of OpenSAML nor the names of its contributors, nor * Internet2, nor the University Corporation for Advanced Internet Development, * Inc., nor UCAID may be used to endorse or promote products derived from this * software without specific prior written permission. For written permission, * please contact opensaml@opensaml.org * * Products derived from this software may not be called OpenSAML, Internet2, * UCAID, or the University Corporation for Advanced Internet Development, nor * may OpenSAML appear in their name, without prior written permission of the * University Corporation for Advanced Internet Development. * * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK * OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE. * IN NO EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY * CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.opensaml;import java.io.BufferedReader;import java.io.FileInputStream;import java.io.InputStreamReader;import java.net.HttpURLConnection;import java.net.MalformedURLException;import java.net.URL;import java.net.URLConnection;import java.util.Iterator;import java.util.StringTokenizer;import java.security.cert.CertificateException;import java.security.cert.X509Certificate;import java.security.KeyManagementException;import java.security.KeyStore;import java.security.KeyStoreException;import java.security.NoSuchAlgorithmException;import java.security.UnrecoverableKeyException;import javax.net.ssl.KeyManagerFactory;import javax.net.ssl.SSLContext;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.log4j.Logger;import org.apache.log4j.NDC;import org.apache.xml.security.c14n.CanonicalizationException;import org.apache.xml.security.c14n.Canonicalizer;import org.apache.xml.security.c14n.InvalidCanonicalizerException;import org.w3c.dom.*;import org.xml.sax.SAXException;/** * Base class for policy-specific SOAP over HTTP binding implementations * * @author Scott Cantor * @created November 25, 2001 */public class SAMLSOAPBinding implements SAMLBinding{ private static Logger log = Logger.getLogger(SAMLSOAPBinding.class.getName()); /** OpenSAML configuration */ protected SAMLConfig config = SAMLConfig.instance(); /** Defeault constructor for a SAMLSOAPBinding object */ public SAMLSOAPBinding() { } /** * Used by requester to send a SAML request to an authority, and obtain a * response in return * * @param bindingInfo Defines the binding protocol and the authority * to contact * @param request SAML request to send * @return SAML response received from authority * @exception SAMLException Base class of exceptions that may be thrown * during processing */ public SAMLResponse send(SAMLAuthorityBinding bindingInfo, SAMLRequest request) throws SAMLException { try { NDC.push("send"); // Turn the request into a DOM, and use its document for the SOAP nodes. Document doc=request.toDOM().getOwnerDocument(); // Build a SOAP envelope and body. Element e=doc.createElementNS(XML.SOAP11ENV_NS, "Envelope"); e.setAttributeNS(XML.XMLNS_NS, "xmlns", XML.SOAP11ENV_NS); Element body=doc.createElementNS(XML.SOAP11ENV_NS, "Body"); e.appendChild(body); // Attach SAML request. body.appendChild(request.toDOM()); if (doc.getDocumentElement()==null) doc.appendChild(e); else doc.replaceChild(e, doc.getDocumentElement()); // Connect to authority. log.debug("connecting to SAML authority at " + bindingInfo.getLocation()); URLConnection conn=new URL(bindingInfo.getLocation()).openConnection(); conn.setAllowUserInteraction(false); conn.setDoOutput(true); ((HttpURLConnection)conn).setInstanceFollowRedirects(false); ((HttpURLConnection)conn).setRequestMethod("POST"); ((HttpURLConnection)conn).setRequestProperty("Content-Type","text/xml; charset=UTF-8"); ((HttpURLConnection)conn).setRequestProperty("SOAPAction","http://www.oasis-open.org/committees/security"); //以上是建立链接,以下是建立SSL通道 if (conn instanceof javax.net.ssl.HttpsURLConnection) { String ks_path=config.getProperty("ssl-keystore"); if (ks_path != null) { String ks_alias=config.getProperty("ssl-alias"); String ks_pwd=config.getProperty("ssl-keystore-pwd"); String key_pwd=config.getProperty("ssl-key-pwd"); KeyStore ks=KeyStore.getInstance("JKS"); ks.load(new FileInputStream(ks_path),(ks_pwd!=null) ? ks_pwd.toCharArray() : null); SSLContext ctx=SSLContext.getInstance("TLS"); KeyManagerFactory kmf=KeyManagerFactory.getInstance("SunX509"); kmf.init(ks,(key_pwd!=null) ? key_pwd.toCharArray() : null); ctx.init(kmf.getKeyManagers(), null, null); ((javax.net.ssl.HttpsURLConnection)conn).setSSLSocketFactory(ctx.getSocketFactory()); } } Canonicalizer c = Canonicalizer.getInstance(Canonicalizer.ALGO_ID_C14N_OMIT_COMMENTS); conn.connect(); conn.getOutputStream().write(c.canonicalizeSubtree(e)); String content_type=((HttpURLConnection)conn).getContentType(); if (!content_type.startsWith("text/xml")) { log.error("send() received an invalid content type in the response (" + content_type + "), with the following content:"); BufferedReader reader=new BufferedReader(new InputStreamReader(conn.getInputStream())); log.error(reader.readLine()); throw new BindingException(SAMLException.RESPONDER,"send() detected an invalid content type in the response: " + content_type); } //以上是发送请求,以下是接受应答 e=XML.parserPool.parse(conn.getInputStream()).getDocumentElement(); // The root must be a SOAP 1.1 envelope. if (!XML.isElementNamed(e,XML.SOAP11ENV_NS,"Envelope")) throw new MalformedException(SAMLException.RESPONDER,"SAMLSOAPBinding::send() detected an incompatible or missing SOAP envelope"); /* Walk the children. If we encounter any headers with mustUnderstand, we have to bail. The thinking here is, we're not a "real" SOAP processor, but we have to emulate one that understands no headers. For now, assume we're the recipient. */ Element n = XML.getFirstChildElement(e); if (XML.isElementNamed(n,XML.SOAP11ENV_NS,"Header")) { Node header=n.getFirstChild(); while (header!=null) { if (header.getNodeType()==Node.ELEMENT_NODE && ((Element)header).getAttributeNS(XML.SOAP11ENV_NS,"mustUnderstand")!=null && ((Element)header).getAttributeNS(XML.SOAP11ENV_NS,"mustUnderstand").equals("1")) throw new SOAPException(SAMLException.RESPONDER,"SAMLSOAPBinding::send() detected a mandatory SOAP header"); header=header.getNextSibling(); } n = XML.getNextSiblingElement(n); // advance to body } if (n != null) { // Get the first (and only) child element of the Body. n = XML.getFirstChildElement(n); if (n != null) { // Is it a fault? if (n.getNodeType() == Node.ELEMENT_NODE && XML.isElementNamed((Element)n,XML.SOAP11ENV_NS,"Fault")) { // Find the faultstring element and use it in the message. NodeList nlist = n.getElementsByTagNameNS(null,"faultstring"); String msg; if (nlist != null && nlist.getLength() > 0) msg = nlist.item(0).getFirstChild().getNodeValue(); else msg = "SAMLSOAPBinding::send() detected a SOAP fault"; nlist = n.getElementsByTagNameNS(null,"faultstring"); if (nlist != null && nlist.getLength() > 0) throw new SOAPException(QName.getQNameTextNode((Text)nlist.item(0).getFirstChild()),msg); else throw new SOAPException(SOAPException.SERVER,msg); } SAMLResponse ret = new SAMLResponse(n); if (!ret.getInResponseTo().equals(request.getId())) { throw new BindingException("SAMLSOAPBinding.send() unable to match SAML InResponseTo value to request"); } return ret; } } throw new SOAPException(SOAPException.SERVER,"SAMLSOAPBinding::send() unable to find a SAML response or fault in SOAP body"); } catch (KeyStoreException ex) { throw new SAMLException("SAMLSOAPBinding.send() caught a keystore exception", ex); } catch (CertificateException ex) { throw new SAMLException("SAMLSOAPBinding.send() caught a certificate exception", ex); } catch (NoSuchAlgorithmException ex) { throw new SAMLException("SAMLSOAPBinding.send() caught a JCE exception", ex); } catch (UnrecoverableKeyException ex) { throw new SAMLException("SAMLSOAPBinding.send() caught a key exception", ex);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -