📄 samltokenverifier.java
字号:
/* * Copyright 2005-2008 WSO2, Inc. (http://wso2.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.wso2.solutions.identity.relyingparty.saml;import java.io.ByteArrayInputStream;import java.io.File;import java.io.FileWriter;import java.io.IOException;import java.net.URI;import java.security.KeyStore;import java.security.PrivateKey;import java.security.cert.X509Certificate;import java.util.ArrayList;import java.util.Hashtable;import java.util.List;import javax.crypto.SecretKey;import javax.xml.parsers.DocumentBuilderFactory;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.apache.ws.security.WSConstants;import org.apache.ws.security.processor.EncryptedKeyProcessor;import org.apache.ws.security.util.DOM2Writer;import org.apache.ws.security.util.WSSecurityUtil;import org.apache.xml.security.Init;import org.apache.xml.security.encryption.XMLCipher;import org.apache.xml.security.utils.EncryptionConstants;import org.opensaml.xml.signature.Signature;import org.opensaml.xml.signature.SignatureValidator;import org.w3c.dom.Document;import org.w3c.dom.Element;import org.wso2.solutions.identity.IdentityConstants;import org.wso2.solutions.identity.i18n.Messages;import org.wso2.solutions.identity.relyingparty.RelyingPartyException;import org.wso2.solutions.identity.relyingparty.TokenVerifierConstants;import org.wso2.solutions.identity.relyingparty.saml.tokens.SAML1TokenHolder;import org.wso2.solutions.identity.relyingparty.saml.tokens.SAML2TokenHolder;import org.wso2.solutions.identity.relyingparty.saml.tokens.TokenHolder;import org.wso2.solutions.identity.relyingparty.servletfilter.RelyingPartyData;/** * A SAML token is sent to a web application in a CardSpace login attempt and * this can be used for decryption and verification of those tokens. */public class SAMLTokenVerifier { private static Log log = LogFactory.getLog(SAMLTokenVerifier.class); private static Messages messages = Messages .getInstance(TokenVerifierConstants.RESOURCES); private Hashtable attributeTable = new Hashtable(); private List certificates = new ArrayList(); private Element keyInfoElement = null; private String issuerName = null; private boolean isMultipleValues = false; private X509Certificate signingCert = null; static { Init.init(); } /** * Decrypt the given token (as a <code>java.lang.String</code> with the * given private key. * @param token Serialized SAML token * @param serviceKey Private key to be used for decryption. * @return Decrypted SAML token element. * @throws RelyingPartyException */ public Element decryptToken(String token, PrivateKey serviceKey) throws RelyingPartyException { try { if (log.isDebugEnabled()) { log.debug(messages.getMessage("receivedEncryuptedToken", new String[] { token })); } ByteArrayInputStream bais = new ByteArrayInputStream(token .getBytes()); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); Document doc = dbf.newDocumentBuilder().parse(bais); Element encryptedTokenElem = doc.getDocumentElement(); // Decrypt element return this.decryptElement(serviceKey, encryptedTokenElem); } catch (Exception e) { throw new RelyingPartyException("verificationFailure", e); } } /** * This method performs two actions 1) Decrypt the token 2) Verify the token * @param decryptedElem SAML token element * @return true if verification is successful and false if unsuccessful. * @throws SAMLException */ public boolean verifyDecryptedToken(Element decryptedElem, RelyingPartyData rpData) throws RelyingPartyException { boolean isValid = true; if (log.isDebugEnabled()) { log.debug(messages.getMessage("verifyingDecryptedToken")); } if (log.isDebugEnabled()) { try { String val = DOM2Writer.nodeToString(decryptedElem); log.debug(val); FileWriter writer = new FileWriter(new File("last_msg.xml")); writer.write(val.toCharArray()); writer.flush(); writer.close(); } catch (IOException e) { log.error(e.getMessage(), e); } } try { String version = decryptedElem.getNamespaceURI(); TokenHolder holder = null; if (version.equals(IdentityConstants.SAML10_URL) || version.equals(IdentityConstants.SAML11_URL)) { holder = new SAML1TokenHolder(); } else if (version.equals(IdentityConstants.SAML20_URL)) { holder = new SAML2TokenHolder(); } else { throw new RelyingPartyException("invalidTokenType", new String[] { version }); } holder.createToken(decryptedElem); issuerName = holder.getIssuerName(); if (issuerName == null) { throw new RelyingPartyException("issuerIsNull"); } Signature sig = holder.getSAMLSignature(); X509CredentialImpl credential = null; if (issuerName.equals(IdentityConstants.SELF_ISSUED_ISSUER)) { credential = (X509CredentialImpl) X509CredentialUtil .loadCredentialFromSignature(sig); this.keyInfoElement = sig.getKeyInfo().getDOM(); } else { String validationPolicy = rpData.getValidatePolicy(); String alias = null; URI uri = new URI(issuerName); alias = uri.getHost(); KeyStore trustStore = rpData.getTrustStore(); KeyStore systemStore = rpData.getSystemStore(); if (trustStore != null && alias != null) { credential = (X509CredentialImpl) X509CredentialUtil .loadCredentialFromTrustStore(alias, trustStore); } boolean isLoadedFromMessage = false; if (credential == null) { credential = (X509CredentialImpl) X509CredentialUtil .loadCredentialFromSignature(sig); if (credential == null) throw new RelyingPartyException("credentialIsNull"); isLoadedFromMessage = true; } if (!validationPolicy .equals(TokenVerifierConstants.PROMISCUOUS)) { this.signingCert = credential.getSigningCert(); if (signingCert == null) throw new RelyingPartyException("signingCertNull"); /* * do certificate validation for blacklist, whitelist and * cert-validity */ signingCert.checkValidity(); if (isLoadedFromMessage) { if (!IssuerCertificateUtil.checkSystemStoree( signingCert, trustStore, systemStore)) { isValid = false; } } if (validationPolicy .equals(TokenVerifierConstants.BLACK_LIST)) { if (!IssuerCertificateUtil.doBlackListCheck(rpData .getBlackList(), signingCert)) { isValid = false; } } if (validationPolicy .equals(TokenVerifierConstants.WHITE_LIST)) { if (!IssuerCertificateUtil.doWhiteListCheck(rpData .getWhiteList(), signingCert)) { isValid = false; } } } } if (isValid) { SignatureValidator validator = new SignatureValidator( credential); validator.validate(sig); holder.populateAttributeTable(this.attributeTable); } } catch (Exception e) { log.debug(e); throw new RelyingPartyException("errorInTokenVerification", new Object[] { e.getMessage() }); } if (log.isDebugEnabled()) { log.debug(messages.getMessage("verifyingDecryptedTokenDone")); } // everything is fine :D return isValid; } private Element decryptElement(PrivateKey privKey, Element encryptedToken) throws Exception { if (log.isDebugEnabled()) { log.debug(messages.getMessage("decryptingToken")); } Element kiElem = (Element) encryptedToken.getElementsByTagNameNS( WSConstants.SIG_NS, "KeyInfo").item(0); Element encrKeyElem = (Element) kiElem.getElementsByTagNameNS( WSConstants.ENC_NS, EncryptionConstants._TAG_ENCRYPTEDKEY) .item(0); EncryptedKeyProcessor encrKeyProcessor = new EncryptedKeyProcessor(); encrKeyProcessor.handleEncryptedKey(encrKeyElem, privKey); SecretKey secretKey = WSSecurityUtil.prepareSecretKey( EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES128, encrKeyProcessor.getDecryptedBytes()); XMLCipher cipher = XMLCipher.getInstance(); cipher.init(XMLCipher.DECRYPT_MODE, secretKey); Document doc = cipher.doFinal(encryptedToken.getOwnerDocument(), encryptedToken); if (log.isDebugEnabled()) { log.debug(messages.getMessage("decryptingTokenDone")); } return doc.getDocumentElement(); } public X509Certificate getSigningCert() { return signingCert; } /** * Returns the list of attributes extracted from the SAMLAttributeStatements * in the verified SAML assertion. * @return List of attributes as a <code>java.util.Hashtable</code> */ public Hashtable getAttributeTable() { return attributeTable; } public List getCertificates() { return certificates; } public Element getKeyInfoElement() { return keyInfoElement; } public String getIssuerName() { return issuerName; } public void setIssuerName(String issuer) { this.issuerName = issuer; } public boolean isMultipleValues() { return isMultipleValues; } public void setMultipleValues(boolean isMultipleValues) { this.isMultipleValues = isMultipleValues; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -