Java 基于SAML请求创建SAML响应

Java 基于SAML请求创建SAML响应,java,saml,saml-2.0,assertions,Java,Saml,Saml 2.0,Assertions,我已经开发了一个JavaWeb应用程序,我想实现SAML。我认为这些是实现SAML的正确步骤 服务提供者(SP,在本例中是我的应用程序)向IdP发送SAML身份验证请求 然后,IdP对其进行验证,创建SAML响应断言,并使用证书对其进行签名,然后发送回SP SP然后使用密钥库中证书的公钥对其进行验证,并在此基础上进一步进行 我有一个示例代码,我能够创建SAML请求,就像这样 <samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2

我已经开发了一个JavaWeb应用程序,我想实现SAML。我认为这些是实现SAML的正确步骤

  • 服务提供者(SP,在本例中是我的应用程序)向IdP发送SAML身份验证请求
  • 然后,IdP对其进行验证,创建SAML响应断言,并使用证书对其进行签名,然后发送回SP
  • SP然后使用密钥库中证书的公钥对其进行验证,并在此基础上进一步进行
  • 我有一个示例代码,我能够创建SAML请求,就像这样

    <samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
        ID="_c7b796f4-bc16-4fcc-8c1d-36befffc39c2" Version="2.0"
        IssueInstant="2014-10-30T11:21:08Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
        AssertionConsumerServiceURL="http://localhost:8080/mywebapp/consume.jsp">
        <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">http://localhost:8080/mywebapp
        </saml:Issuer>
        <samlp:NameIDPolicy
            Format="urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified"
            AllowCreate="true"></samlp:NameIDPolicy>
        <samlp:RequestedAuthnContext Comparison="exact">
            <saml:AuthnContextClassRef xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
            </saml:AuthnContextClassRef>
        </samlp:RequestedAuthnContext>
    </samlp:AuthnRequest>
    
    
    http://localhost:8080/mywebapp
    urn:oasis:name:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
    
    我可以对它进行编码并发送到IdP

    我想创建示例Java代码来获取这个SAML请求,然后创建一个SAML响应。 如何解码请求、验证请求并创建响应?我需要用证书签署saml响应吗?然后发送回SP


    谢谢。

    您列出的步骤或多或少都是正确的。我要指出的唯一一点是,如果单词sends(例如,“SP…向IdP发送SAML身份验证请求”)的含义,您必须小心。SAML允许SP和IdP之间零直接通信的身份验证场景

    另一个小的补充是SP也可以签署他的请求,因此您可以在双方进行签名验证。SP端的验证是强制性的

    例如,如果要实现SAML,可能需要检查现有的解决方案之一。如果你在Spring和JBoss这样的平台上,你可能想检查一下或者。如果你想去低一层,检查一下


    在我的公司,JBoss是我们的标准配置,我们对此非常满意。

    您列出的步骤或多或少都是正确的。我要指出的唯一一点是,如果单词sends(例如,“SP…向IdP发送SAML身份验证请求”)的含义,您必须小心。SAML允许SP和IdP之间零直接通信的身份验证场景

    另一个小的补充是SP也可以签署他的请求,因此您可以在双方进行签名验证。SP端的验证是强制性的

    例如,如果要实现SAML,可能需要检查现有的解决方案之一。如果你在Spring和JBoss这样的平台上,你可能想检查一下或者。如果你想去低一层,检查一下


    在我的公司里,JBoss是我们的标准配置,我们对此非常满意。

    虽然这是一篇老文章,但我正在添加一些示例代码和参考资料,我发现它们很有用

    SAMLResponse = hreq.getParameter("SAMLResponse");
    InputSource inputSource = new InputSource(new StringReader(SAMLResponse));
    SAMLReader samlReader = new SAMLReader();                   
    response2 = org.opensaml.saml2.core.Response)samlReader.readFromFile(inputSource);
    
    现在验证数字签名:

    org.opensaml.saml2.core.Response response2 = (org.opensaml.saml2.core.Response)samlReader.readFromFile(inputSource);  
    //To fetch the digital signature from the response.
    Signature signature  = response2.getSignature(); 
    X509Certificate certificate = (X509Certificate) keyStore.getCertificate(domainName);
    //pull out the public key part of the certificate into a KeySpec
    X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(certificate.getPublicKey().getEncoded());
    //get KeyFactory object that creates key objects, specifying RSA - java.security.KeyFactory
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");                  
    //generate public key to validate signatures
    PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
    //we have the public key                    
    BasicX509Credential publicCredential = new BasicX509Credential();
    //add public key value
    publicCredential.setPublicKey(publicKey);
    //create SignatureValidator
    SignatureValidator signatureValidator = new SignatureValidator(publicCredential);
    //try to validate
    try{
    signatureValidator.validate(signature); 
    catch(Exception e){
    //
    } 
    
    现在获取断言映射:

    samlDetailsMap = setSAMLDetails(response2);
    
    在上面的逻辑中,使用下面的私有方法来提取所有断言属性。最后,您将拥有发送给您的所有字段的地图

     private Map<String, String> setSAMLDetails(org.opensaml.saml2.core.Response  response2){
            Map<String, String> samlDetailsMap = new HashMap<String, String>();
            try {
                List<Assertion> assertions = response2.getAssertions();
                LOGGER.error("No of assertions : "+assertions.size());
                for(Assertion assertion:assertions){
                    List<AttributeStatement> attributeStatements = assertion.getAttributeStatements();
                    for(AttributeStatement attributeStatement: attributeStatements){
                        List<Attribute> attributes = attributeStatement.getAttributes();
                        for(Attribute attribute: attributes){
                            String name = attribute.getName();                          
                            List<XMLObject> attributes1 = attribute.getAttributeValues();
                            for(XMLObject xmlObject : attributes1){
                                if(xmlObject instanceof XSString){
                                    samlDetailsMap.put(name, ((XSString) xmlObject).getValue());
                                    LOGGER.error("Name is : "+name+" value is : "+((XSString) xmlObject).getValue());
                                }else if(xmlObject instanceof XSAnyImpl){
                                    String value = ((XSAnyImpl) xmlObject).getTextContent();
    
                                    samlDetailsMap.put(name, value);
    
                                }         
                        }
                    }
                }       
           }
          } catch (Exception e) {             
              LOGGER.error("Exception occurred while setting the saml details");        
            }       
            LOGGER.error("Exiting from  setSAMLDetails method"); 
            return samlDetailsMap;
        }
    

    }

    虽然这是一篇老文章,但我添加了一些我觉得有用的示例代码和参考资料

    SAMLResponse = hreq.getParameter("SAMLResponse");
    InputSource inputSource = new InputSource(new StringReader(SAMLResponse));
    SAMLReader samlReader = new SAMLReader();                   
    response2 = org.opensaml.saml2.core.Response)samlReader.readFromFile(inputSource);
    
    现在验证数字签名:

    org.opensaml.saml2.core.Response response2 = (org.opensaml.saml2.core.Response)samlReader.readFromFile(inputSource);  
    //To fetch the digital signature from the response.
    Signature signature  = response2.getSignature(); 
    X509Certificate certificate = (X509Certificate) keyStore.getCertificate(domainName);
    //pull out the public key part of the certificate into a KeySpec
    X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(certificate.getPublicKey().getEncoded());
    //get KeyFactory object that creates key objects, specifying RSA - java.security.KeyFactory
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");                  
    //generate public key to validate signatures
    PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
    //we have the public key                    
    BasicX509Credential publicCredential = new BasicX509Credential();
    //add public key value
    publicCredential.setPublicKey(publicKey);
    //create SignatureValidator
    SignatureValidator signatureValidator = new SignatureValidator(publicCredential);
    //try to validate
    try{
    signatureValidator.validate(signature); 
    catch(Exception e){
    //
    } 
    
    现在获取断言映射:

    samlDetailsMap = setSAMLDetails(response2);
    
    在上面的逻辑中,使用下面的私有方法来提取所有断言属性。最后,您将拥有发送给您的所有字段的地图

     private Map<String, String> setSAMLDetails(org.opensaml.saml2.core.Response  response2){
            Map<String, String> samlDetailsMap = new HashMap<String, String>();
            try {
                List<Assertion> assertions = response2.getAssertions();
                LOGGER.error("No of assertions : "+assertions.size());
                for(Assertion assertion:assertions){
                    List<AttributeStatement> attributeStatements = assertion.getAttributeStatements();
                    for(AttributeStatement attributeStatement: attributeStatements){
                        List<Attribute> attributes = attributeStatement.getAttributes();
                        for(Attribute attribute: attributes){
                            String name = attribute.getName();                          
                            List<XMLObject> attributes1 = attribute.getAttributeValues();
                            for(XMLObject xmlObject : attributes1){
                                if(xmlObject instanceof XSString){
                                    samlDetailsMap.put(name, ((XSString) xmlObject).getValue());
                                    LOGGER.error("Name is : "+name+" value is : "+((XSString) xmlObject).getValue());
                                }else if(xmlObject instanceof XSAnyImpl){
                                    String value = ((XSAnyImpl) xmlObject).getTextContent();
    
                                    samlDetailsMap.put(name, value);
    
                                }         
                        }
                    }
                }       
           }
          } catch (Exception e) {             
              LOGGER.error("Exception occurred while setting the saml details");        
            }       
            LOGGER.error("Exiting from  setSAMLDetails method"); 
            return samlDetailsMap;
        }
    

    }

    我想测试我的应用程序。我已经创建了SAML请求。我尝试了一些IdP,但不是免费的。所以我尝试创建自己的SAML响应。我有一份证书样本。我想在回复上签名并发送到我的应用程序。我想你可以免费使用SalesForce进行测试。这里是PicketLink的文档,但您也可以将其应用于SP:如何使用java代码从SAMLResponse获取Samlasertion?我想测试我的应用程序。我已经创建了SAML请求。我尝试了一些IdP,但不是免费的。所以我尝试创建自己的SAML响应。我有一份证书样本。我想在回复上签名并发送到我的应用程序。我想你可以免费使用SalesForce进行测试。这里是PicketLink的文档,但您也可以将其应用于SP:我们如何使用java代码从SAMLResponse获取Samlasertion?