无法在SAMLResponse中获取签名值

时间:2015-10-21 08:25:19

标签: java opensaml

我已将我的网站与TFIM集成用于SSO。 SSO工作正常,但我无法在SAMLResponse中获得签名。 它变为空。但它已经存在于SAMLResponse中。 当我试图从samlresponse获取签名值时,它会给我nullpointerexception

package com.saml;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.opensaml.Configuration;
import org.opensaml.DefaultBootstrap;
import org.opensaml.saml2.core.Response;
import org.opensaml.saml2.core.Subject;
import org.opensaml.security.SAMLSignatureProfileValidator;
import org.opensaml.xml.ConfigurationException;
import org.opensaml.xml.XMLObject;
import org.opensaml.xml.io.Unmarshaller;
import org.opensaml.xml.io.UnmarshallerFactory;
import org.opensaml.xml.io.UnmarshallingException;
import org.opensaml.xml.security.credential.Credential;
import org.opensaml.xml.security.x509.BasicX509Credential;
import org.opensaml.xml.signature.SignatureValidator;
import org.apache.commons.codec.binary.Base64;
import org.opensaml.xml.validation.ValidationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

public class ReceiveSAMLResponse {

    public String receiveSAMLResponse(HttpServletRequest request)
            throws ParserConfigurationException, SAXException, IOException,
            UnmarshallingException, ValidationException, CertificateException {
        /* Getting the response string from HTTP Request object */
        String responseString = (String) request.getParameter("SAMLResponse");

        /* Decoding Base64 response string to get the XML string */

        String responseXml = new String(Base64.decodeBase64(responseString
                .getBytes()));

        System.out.println(responseXml);
        /* Generating SAML Response object from XML string */
        try {
            DefaultBootstrap.bootstrap();
        } catch (ConfigurationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory
                .newInstance();
        documentBuilderFactory.setNamespaceAware(true);
        DocumentBuilder docBuilder = documentBuilderFactory
                .newDocumentBuilder();
        ByteArrayInputStream is = new ByteArrayInputStream(
                responseXml.getBytes());
        Document document = docBuilder.parse(is);
        Element element = document.getDocumentElement();

        UnmarshallerFactory unmarshallerFactory = Configuration
                .getUnmarshallerFactory();

        Unmarshaller unmarshaller = unmarshallerFactory
                .getUnmarshaller(element);

        XMLObject xmlObj = unmarshaller.unmarshall(element);
        Response response = (Response) xmlObj;

        /* Validating the signature on the response */
        // validateSignature(response);

        /* If validation was successful, get the username from the response. */
        Subject subject = response.getAssertions().get(0).getSubject();
        String username = subject.getNameID().getValue();
        return username;
    }

    private void validateSignature(Response response)
            throws ValidationException, FileNotFoundException,
            CertificateException {
        SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator();
        try {
            profileValidator.validate(response.getSignature());
        } catch (ValidationException e) {
            /* Indicates signature did not conform to SAML Signature profile */
            e.printStackTrace();
            throw e;
        }

        Credential verificationCredential = getVerificationCredential();
        SignatureValidator sigValidator = new SignatureValidator(
                verificationCredential);
        try {
            sigValidator.validate(response.getSignature());
        } catch (ValidationException e) {

            e.printStackTrace();
            throw e;
        }
    }

    private Credential getVerificationCredential()
            throws FileNotFoundException, CertificateException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
                "/pathToYourCertificte"));
        CertificateFactory cf = CertificateFactory.getInstance("X509");
        X509Certificate cert = (X509Certificate) cf.generateCertificate(bis);
        BasicX509Credential x509Credential = new BasicX509Credential();
        x509Credential.setPublicKey(cert.getPublicKey());
        x509Credential.setEntityCertificate(cert);
        Credential credential = x509Credential;
        return credential;
    }

}

....................................

xml文件中的saml响应

<samlp:Response xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Destination="https://10.44.90.29:8443/SAMLShareFile/saml/samlresponse" ID="FIMRSP_604af2be-0150-1ff0-adad-8154af08b58c" InResponseTo="-5346144739450824145" IssueInstant="2015-10-13T08:22:15Z" Version="2.0"><saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://10.44.189.168:444/apjct/sps/NewRelic/saml20</saml:Issuer><samlp:Status><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"></samlp:StatusCode></samlp:Status><saml:Assertion ID="Assertion-uuid604af281-0150-1512-8c38-8154af08b58c" IssueInstant="2015-10-13T08:22:15Z" Version="2.0"><saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://10.44.189.168:444/apjct/sps/NewRelic/saml20</saml:Issuer><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="uuid604af289-0150-1dab-a25e-8154af08b58c"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:CanonicalizationMethod><ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></ds:SignatureMethod><ds:Reference URI="#Assertion-uuid604af281-0150-1512-8c38-8154af08b58c"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"><xc14n:InclusiveNamespaces xmlns:xc14n="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="xs saml xsi"></xc14n:InclusiveNamespaces></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod><ds:DigestValue>pMf0E/z1rS9OkTOLc+0aoD7cl30=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>SW9BaJm0rGJAOG62Il1v46YsqocHXNpmcQKAmSIKDX4tRN3EbUHeqFcVfJmmUGDe4uC1H115SOCehQAkJ35lLBnVsda2WHgu4kWdGC8j+kaw0y9zjzngrHZljBpzU2h87zk4X+fGXvtCmBUH7xfrID4tQ6ODdhoWjd6K8s21S50=</ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIICBzCCAXCgAwIBAgIEQH26vjANBgkqhkiG9w0BAQQFADBIMQswCQYDVQQGEwJVUzEPMA0GA1UEChMGVGl2b2xpMQ4wDAYDVQQLEwVUQU1lQjEYMBYGA1UEAxMPZmltZGVtby5pYm0uY29tMB4XDTA0MDQxNDIyMjcxMFoXDTE3MTIyMjIyMjcxMFowSDELMAkGA1UEBhMCVVMxDzANBgNVBAoTBlRpdm9saTEOMAwGA1UECxMFVEFNZUIxGDAWBgNVBAMTD2ZpbWRlbW8uaWJtLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAiZ0D1X6rk8+ZwNBTVZt7C85m421a8A52Ksjw40t+jNvbLYDp/W66AMMYD7rB5qgniZ5K1p9W8ivM9WbPxc2u/60tFPg0e/Q/r/fxegW1K1umnay+5MaUvN3p4XUCRrfg79OvurvXQ7GZa1/wOp5vBIdXzg6i9CVAqL29JGi6GYUCAwEAATANBgkqhkiG9w0BAQQFAAOBgQBXiAhxm91I4m+g3YX+dyGc352TSKO8HvAIBkHHFFwIkzhNgO+zLhxg5UMkOg12X9ucW7leZ1IB0Z6+JXBrXIWmU3UPum+QxmlaE0OG9zhp9LEfzsE5+ff+7XpS0wpJklY6c+cqHj4aTGfOhSE6u7BLdI26cZNdzxdhikBMZPgdyQ==</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature><saml:Subject><saml:NameID Format="urn:ibm:names:ITFIM:5.1:accessmanager">musaddique</saml:NameID><saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml:SubjectConfirmationData InResponseTo="-5346144739450824145" NotOnOrAfter="2015-10-13T08:32:15Z" Recipient="https://10.44.90.29:8443/SAMLShareFile/saml/samlresponse"></saml:SubjectConfirmationData></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore="2015-10-13T08:12:15Z" NotOnOrAfter="2015-10-13T08:32:15Z"><saml:AudienceRestriction><saml:Audience>musaddique</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant="2015-10-13T08:22:15Z" SessionIndex="uuid604af260-0150-14b6-8127-8154af08b58c" SessionNotOnOrAfter="2015-10-13T09:22:15Z"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement><saml:Attribute Name="AuthenticatingAuthority" NameFormat="urn:oasis:names:tc:SAML:2.0:assertion"><saml:AttributeValue xsi:type="xs:string">musaddique</saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion></samlp:Response>

2 个答案:

答案 0 :(得分:3)

你的SAML只有assertion part()被签名,所以你应该从assertion对象而不是响应对象获得签名:try response.getAssertions()。get(0).getSignature()。 基于SAML 2.0规范,必须对SAML响应进行签名,但并非强制要求响应和sssertion。

答案 1 :(得分:0)

我在SamlProvider中编写了这段代码。我没有使用它,因为Idp没有在saml中请求HTTPS协议和证书,因此它不是“认证解决方案”我从文件中加载证书,因此您可以直接注入BufferedInputStream。

private Credential getCredential() {
        BasicX509Credential credential = null;
        try {
            // read private key
            File privateKeyFile = new File(derFile);
            FileInputStream inputStreamPrivateKey = new FileInputStream(privateKeyFile);
            byte[] encodedPrivateKey = new byte[(int) privateKeyFile.length()];
            inputStreamPrivateKey.read(encodedPrivateKey);
            inputStreamPrivateKey.close();
            PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encodedPrivateKey);
            RSAPrivateKey privateKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(
                    privateKeySpec);
            // read the certificate
            InputStream inStream = new FileInputStream(pemFile);
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            X509Certificate cert = (X509Certificate) cf.generateCertificate(inStream);
            // create credential
            credential = new BasicX509Credential();
            credential.setEntityCertificate((java.security.cert.X509Certificate) cert);
            credential.setPrivateKey(privateKey);
        } catch (Exception e) {
            Logger.error("failed getting credential!", e);
        }
        return credential;
    }

希望它有所帮助。