SalesForce рдХреЗ рд▓рд┐рдП рдПрдХрд▓ рд╕рд╛рдЗрди-рдСрди рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди

3 рджрд┐рдиреЛрдВ рдХреА рдкреАрдбрд╝рд╛ рдФрд░ рдмрд┐рдХреНрд░реА рдХреЗ рдмрд╛рдж SSO рдХреЛ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмреЗрдХрд╛рд░ рдХреЗ рдкреНрд░рдпрд╛рд╕реЛрдВ рдХреЗ рдмрд╛рдж, рдореИрдВ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдореБрджрд╛рдп рдХреЗ рд╕рд╛рде рд╕рд╣реА рддрд░реАрдХреЗ рд╕реЗ рд╕рд╛рдЭрд╛ рдХрд░рдиреЗ рдХреА рдЬрд▓реНрджрдмрд╛рдЬреА рдХрд░рддрд╛ рд╣реВрдВ, рддрд╛рдХрд┐ рдЖрдиреЗ рд╡рд╛рд▓реА рдкреАрдврд╝рд┐рдпрд╛рдВ рдХреАрдорддреА рд╕рдордп рдХреА рд╕рдлрд▓рддрд╛ рдХреЗ рд▓рд┐рдП рджреАрд╡рд╛рд░ рдХреЗ рдЦрд┐рд▓рд╛рдл рд╕рд┐рд░ рдкреАрдЯрдиреЗ рдореЗрдВ рдЦрд░реНрдЪ рди рдХрд░реЗрдВред рдЕрдЧрд░ рджрд┐рд▓рдЪрд╕реНрдкреА рд╣реИ, рддреЛ рдореИрдВ рдПрдХ рдмрд┐рд▓реНрд▓реА рдХреЗ рд▓рд┐рдП рдкреВрдЫрддрд╛ рд╣реВрдВред

рдПрд╕рдПрд╕рдУ (рд╕рд┐рдВрдЧрд▓ рд╕рд╛рдЗрди-рдСрди) рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╡рд┐рдХреА рдХреЛ рдмрддрд╛рдирд╛ рдмреЗрд╣рддрд░ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдореИрдВ рдЙрдЪреНрдЪ рд╢рдмреНрджрд╛рдВрд╢ рдХрд╛ рдорд╛рд╕реНрдЯрд░ рдирд╣реАрдВ рд╣реВрдВред
рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рдХрд┐рд╕реА рд╕реЗрд╡рд╛ рдЬреИрд╕реЗ SalesForce рдХреЗ рд▓рд┐рдП SSO рд╕рдорд░реНрдерди рдХреЛ рд╡реНрдпрд╡рд╕реНрдерд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдЪреВрдВрдХрд┐ рдПрд╕рдПрдПрдордПрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рд╕рд░реНрд╡рд░реЛрдВ рдХреЗ рдмреАрдЪ рд╕рдВрдЪрд╛рд░ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП Google рдХреЛ рддреИрдпрд╛рд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд▓рд┐рдП рдЦреЛрдЬреЛрдВ рдХреЗ рд╕рд╛рде рдкреАрдбрд╝рд╛ рджреЗрдирд╛ рддрдп рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рд▓рдЧрд╛рддрд╛рд░ рдЦреЛрдЬ рдХреЗ рдмрд╛рдж, рдУрдкрдирдПрд╕рдПрдПрдордПрд▓ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдПрд╕рдПрдПрдордПрд▓ рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд╛рдпрд╛ рдЧрдпрд╛, рдЬрд┐рд╕рдиреЗ рдмреНрд░рд╣реНрдорд╛рдВрдб рдХреЛ рджреВрд╕рд░реА рдмрд╛рдЗрдХ рдХреЗ рдЬрдиреНрдо рд╕реЗ рдмрдЪрд╛рдпрд╛ред

рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ рд╣рдо рдкреНрд░рдорд╛рдг рдкрддреНрд░ рдЙрддреНрдкрдиреНрди рдХрд░реЗрдВрдЧреЗред рдореИрдВрдиреЗ JDK рд╕реЗ keytool рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рд╣реИ рд▓реЗрдХрд┐рди рдЖрдк OpenSSL рдХрд╛ рднреА рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
keytool -genkey -keyalg RSA -alias SSO -keystore keystore keytool -export -alias SSO -keystore keystore -file certificate.crt 


рдХреБрдВрдЬрд┐рдпрд╛рдБ рдЙрддреНрдкрдиреНрди рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЛ SSO рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд▓реЙрдЧрд┐рди рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП SalesForce рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдЙрдирдХреА Wiki рдкрд░ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рдирд┐рд░реНрджреЗрд╢ рд╣реИ - Force.com рдкрд░ SAML рдХреЗ рд╕рд╛рде рд╕рд┐рдВрдЧрд▓ рд╕рд╛рдЗрди-рдСрди ред рд▓реЗрдЦ рдЕрдЪреНрдЫрд╛ рдФрд░ рдмрдврд╝рд┐рдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╣рдореЗрдВ рдХреЗрд╡рд▓ рдПрдХ рдЖрдЗрдЯрдо рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, "SSO рдХреЗ рд▓рд┐рдП Force.com рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдирд╛"ред рд╣рд╛рдВ, рдФрд░ рдпрд╣ рдорд╛рдореВрд▓реА рдмрджрд▓рд╛рд╡реЛрдВ рдХреЗ рд╕рд╛рде рд╣реИ: рдЪреВрдВрдХрд┐ рдореЗрд░рд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди NameIdentifier рддрддреНрд╡ рдореЗрдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдирд╛рдо рд╕реЗ рдЧреБрдЬрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдЙрдирдХреЗ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд╕реНрд╡рд┐рдЪ рдЫреЛрдбрд╝ рджреЗрддреЗ рд╣реИрдВ: "рджрд╛рд╡реЗ рдореЗрдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХрд╛ salesforce.com рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдирд╛рдо рд╣реИ" рдФрд░ "рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЖрдИрдбреА рд╕рдмреНрдЬреЗрдХреНрдЯ рд╕реНрдЯреЗрдЯрдореЗрдВрдЯ рдХреЗ NameIdentifier рддрддреНрд╡ рдореЗрдВ рд╣реИ"ред

рдЪреВрдВрдХрд┐ OpenSAML рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдЙрджрд╛рд╣рд░рдг рдкрд╛рдП рдЧрдП рдереЗ, рдЗрд╕рд▓рд┐рдП рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдЬрдирд░реЗрдЯрд░ рдЬрд▓реНрджреА рд╕реЗ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рдерд╛ рдЬреЛ рдкрд░реАрдХреНрд╖рдг рдХреА рдЬрд░реВрд░рддреЛрдВ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреБрдХреНрдд рдерд╛ред рдХреЛрдб рдХреЛ рдЪрд╛рдЯрдиреЗ рдкрд░ рдмрд┐рддрд╛рдП рдЧрдП рдПрдХ рдХрд╛рд░реНрдп рджрд┐рд╡рд╕ рдХреЗ рдмрд╛рдж, рд╡реИрдз рдПрд╕рдПрдПрдордПрд▓ рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рдПрдХ рдЬрдирд░реЗрдЯрд░ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ (рд╕реЗрд▓реНрд╕рдлреНрд░реАрдб рд╡реИрд▓рд┐рдбреЗрдЯрд░ рдХреЗ рдЕрдиреБрд╕рд╛рд░)ред рдиреАрдЪреЗ рдкрд╛рд▓рд╛ рдХреЛрдб рд╣реИред

рдЪреВрдВрдХрд┐ рдЗрд╕реЗ SalesForce рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдЕрдиреНрдп рд╕реЗрд╡рд╛рдУрдВ рдХреЗ рд╕рдорд░реНрдерди рдХреЛ рдХрд╕рдиреЗ рдХреА рдпреЛрдЬрдирд╛ рдмрдирд╛рдИ рдЧрдИ рд╣реИ, рдЬрдирд░реЗрдЯрд░ рдХреЛ рдХрдИ рд╡рд░реНрдЧреЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ: рд╕рд╛рдорд╛рдиреНрдп рднрд╛рдЧ (SAMLResponseGenerator), SalesForce рдХреЗ рд▓рд┐рдП рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди (SalesforceSAMLResponseGenerator) рдФрд░ рдпрд╣ рд╕рдм рдЧрдбрд╝рдмрдбрд╝ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рд░реНрдпрдХреНрд░рдо:

SAMLResponseGenerator.java:
 public abstract class SAMLResponseGenerator { private static XMLObjectBuilderFactory builderFactory = null; private String issuerId; private X509Certificate certificate; private PublicKey publicKey; private PrivateKey privateKey; protected abstract Assertion buildAssertion(); public SAMLResponseGenerator(X509Certificate certificate, PublicKey publicKey, PrivateKey privateKey, String issuerId) { this.certificate = certificate; this.publicKey = publicKey; this.privateKey = privateKey; this.issuerId = issuerId; } public String generateSAMLAssertionString() throws UnrecoverableKeyException, InvalidKeyException, NoSuchAlgorithmException, CertificateException, KeyStoreException, NoSuchProviderException, SignatureException, MarshallingException, ConfigurationException, IOException, org.opensaml.xml.signature.SignatureException, UnmarshallingException { Response response = buildDefaultResponse(issuerId); Assertion assertion = buildAssertion(); response.getAssertions().add(assertion); assertion = signObject(assertion, certificate, publicKey, privateKey); response = signObject(response, certificate, publicKey, privateKey); Element plaintextElement = marshall(response); return XMLHelper.nodeToString(plaintextElement); } @SuppressWarnings("unchecked") protected <T extends XMLObject> XMLObjectBuilder<T> getXMLObjectBuilder(QName qname) throws ConfigurationException { if (builderFactory == null) { // OpenSAML 2.3 DefaultBootstrap.bootstrap(); builderFactory = Configuration.getBuilderFactory(); } return (XMLObjectBuilder<T>) builderFactory.getBuilder(qname); } protected <T extends XMLObject> T buildXMLObject(QName qname) throws ConfigurationException { XMLObjectBuilder<T> keyInfoBuilder = getXMLObjectBuilder(qname); return keyInfoBuilder.buildObject(qname); } protected Attribute buildStringAttribute(String name, String value) throws ConfigurationException { Attribute attrFirstName = buildXMLObject(Attribute.DEFAULT_ELEMENT_NAME); attrFirstName.setName(name); attrFirstName.setNameFormat(Attribute.UNSPECIFIED); // Set custom Attributes XMLObjectBuilder<XSString> stringBuilder = getXMLObjectBuilder(XSString.TYPE_NAME); XSString attrValueFirstName = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSString.TYPE_NAME); attrValueFirstName.setValue(value); attrFirstName.getAttributeValues().add(attrValueFirstName); return attrFirstName; } private <T extends XMLObject> Element marshall(T object) throws MarshallingException { return Configuration.getMarshallerFactory().getMarshaller(object).marshall(object); } @SuppressWarnings("unchecked") private <T extends XMLObject> T unmarshall(Element element) throws MarshallingException, UnmarshallingException { return (T) Configuration.getUnmarshallerFactory().getUnmarshaller(element).unmarshall(element); } protected <T extends SignableSAMLObject> T signObject(T object, X509Certificate certificate, PublicKey publicKey, PrivateKey privateKey) throws MarshallingException, ConfigurationException, IOException, UnrecoverableKeyException, InvalidKeyException, NoSuchAlgorithmException, CertificateException, KeyStoreException, NoSuchProviderException, SignatureException, org.opensaml.xml.signature.SignatureException, UnmarshallingException { BasicX509Credential signingCredential = new BasicX509Credential(); signingCredential.setEntityCertificate(certificate); signingCredential.setPrivateKey(privateKey); signingCredential.setPublicKey(publicKey); KeyInfo keyInfo = buildXMLObject(KeyInfo.DEFAULT_ELEMENT_NAME); X509Data x509Data = buildXMLObject(X509Data.DEFAULT_ELEMENT_NAME); org.opensaml.xml.signature.X509Certificate x509Certificate = buildXMLObject(org.opensaml.xml.signature.X509Certificate.DEFAULT_ELEMENT_NAME); x509Certificate.setValue(Base64.encodeBase64String(certificate.getEncoded())); x509Data.getX509Certificates().add(x509Certificate); keyInfo.getX509Datas().add(x509Data); Signature signature = buildXMLObject(Signature.DEFAULT_ELEMENT_NAME); signature.setSigningCredential(signingCredential); signature.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1); signature.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS); signature.setKeyInfo(keyInfo); object.setSignature(signature); Element element = marshall(object); Signer.signObject(signature); return unmarshall(element); } protected Response buildDefaultResponse(String issuerId) { try { DateTime now = new DateTime(); // Create Status StatusCode statusCode = buildXMLObject(StatusCode.DEFAULT_ELEMENT_NAME); statusCode.setValue(StatusCode.SUCCESS_URI); Status status = buildXMLObject(Status.DEFAULT_ELEMENT_NAME); status.setStatusCode(statusCode); // Create Issuer Issuer issuer = buildXMLObject(Issuer.DEFAULT_ELEMENT_NAME); issuer.setValue(issuerId); issuer.setFormat(Issuer.ENTITY); // Create the response Response response = buildXMLObject(Response.DEFAULT_ELEMENT_NAME); response.setIssuer(issuer); response.setStatus(status); response.setIssueInstant(now); response.setVersion(SAMLVersion.VERSION_20); return response; } catch (Exception e) { e.printStackTrace(); } return null; } public String getIssuerId() { return issuerId; } public void setIssuerId(String issuerId) { this.issuerId = issuerId; } } (рдЯреА рд╡рд╕реНрддреБ, X509Certificate рдкреНрд░рдорд╛рдг рдкрддреНрд░, PublicKey publicKey, PrivateKey privateKey) рдлреЗрдВрдХрддрд╛ MarshallingException, ConfigurationException, IOException, UnrecoverableKeyException, InvalidKeyException, NoSuchAlgorithmException, CertificateException, KeyStoreException, NoSuchProviderException, SignatureException, org.opensaml.xml.signatureред public abstract class SAMLResponseGenerator { private static XMLObjectBuilderFactory builderFactory = null; private String issuerId; private X509Certificate certificate; private PublicKey publicKey; private PrivateKey privateKey; protected abstract Assertion buildAssertion(); public SAMLResponseGenerator(X509Certificate certificate, PublicKey publicKey, PrivateKey privateKey, String issuerId) { this.certificate = certificate; this.publicKey = publicKey; this.privateKey = privateKey; this.issuerId = issuerId; } public String generateSAMLAssertionString() throws UnrecoverableKeyException, InvalidKeyException, NoSuchAlgorithmException, CertificateException, KeyStoreException, NoSuchProviderException, SignatureException, MarshallingException, ConfigurationException, IOException, org.opensaml.xml.signature.SignatureException, UnmarshallingException { Response response = buildDefaultResponse(issuerId); Assertion assertion = buildAssertion(); response.getAssertions().add(assertion); assertion = signObject(assertion, certificate, publicKey, privateKey); response = signObject(response, certificate, publicKey, privateKey); Element plaintextElement = marshall(response); return XMLHelper.nodeToString(plaintextElement); } @SuppressWarnings("unchecked") protected <T extends XMLObject> XMLObjectBuilder<T> getXMLObjectBuilder(QName qname) throws ConfigurationException { if (builderFactory == null) { // OpenSAML 2.3 DefaultBootstrap.bootstrap(); builderFactory = Configuration.getBuilderFactory(); } return (XMLObjectBuilder<T>) builderFactory.getBuilder(qname); } protected <T extends XMLObject> T buildXMLObject(QName qname) throws ConfigurationException { XMLObjectBuilder<T> keyInfoBuilder = getXMLObjectBuilder(qname); return keyInfoBuilder.buildObject(qname); } protected Attribute buildStringAttribute(String name, String value) throws ConfigurationException { Attribute attrFirstName = buildXMLObject(Attribute.DEFAULT_ELEMENT_NAME); attrFirstName.setName(name); attrFirstName.setNameFormat(Attribute.UNSPECIFIED); // Set custom Attributes XMLObjectBuilder<XSString> stringBuilder = getXMLObjectBuilder(XSString.TYPE_NAME); XSString attrValueFirstName = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSString.TYPE_NAME); attrValueFirstName.setValue(value); attrFirstName.getAttributeValues().add(attrValueFirstName); return attrFirstName; } private <T extends XMLObject> Element marshall(T object) throws MarshallingException { return Configuration.getMarshallerFactory().getMarshaller(object).marshall(object); } @SuppressWarnings("unchecked") private <T extends XMLObject> T unmarshall(Element element) throws MarshallingException, UnmarshallingException { return (T) Configuration.getUnmarshallerFactory().getUnmarshaller(element).unmarshall(element); } protected <T extends SignableSAMLObject> T signObject(T object, X509Certificate certificate, PublicKey publicKey, PrivateKey privateKey) throws MarshallingException, ConfigurationException, IOException, UnrecoverableKeyException, InvalidKeyException, NoSuchAlgorithmException, CertificateException, KeyStoreException, NoSuchProviderException, SignatureException, org.opensaml.xml.signature.SignatureException, UnmarshallingException { BasicX509Credential signingCredential = new BasicX509Credential(); signingCredential.setEntityCertificate(certificate); signingCredential.setPrivateKey(privateKey); signingCredential.setPublicKey(publicKey); KeyInfo keyInfo = buildXMLObject(KeyInfo.DEFAULT_ELEMENT_NAME); X509Data x509Data = buildXMLObject(X509Data.DEFAULT_ELEMENT_NAME); org.opensaml.xml.signature.X509Certificate x509Certificate = buildXMLObject(org.opensaml.xml.signature.X509Certificate.DEFAULT_ELEMENT_NAME); x509Certificate.setValue(Base64.encodeBase64String(certificate.getEncoded())); x509Data.getX509Certificates().add(x509Certificate); keyInfo.getX509Datas().add(x509Data); Signature signature = buildXMLObject(Signature.DEFAULT_ELEMENT_NAME); signature.setSigningCredential(signingCredential); signature.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1); signature.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS); signature.setKeyInfo(keyInfo); object.setSignature(signature); Element element = marshall(object); Signer.signObject(signature); return unmarshall(element); } protected Response buildDefaultResponse(String issuerId) { try { DateTime now = new DateTime(); // Create Status StatusCode statusCode = buildXMLObject(StatusCode.DEFAULT_ELEMENT_NAME); statusCode.setValue(StatusCode.SUCCESS_URI); Status status = buildXMLObject(Status.DEFAULT_ELEMENT_NAME); status.setStatusCode(statusCode); // Create Issuer Issuer issuer = buildXMLObject(Issuer.DEFAULT_ELEMENT_NAME); issuer.setValue(issuerId); issuer.setFormat(Issuer.ENTITY); // Create the response Response response = buildXMLObject(Response.DEFAULT_ELEMENT_NAME); response.setIssuer(issuer); response.setStatus(status); response.setIssueInstant(now); response.setVersion(SAMLVersion.VERSION_20); return response; } catch (Exception e) { e.printStackTrace(); } return null; } public String getIssuerId() { return issuerId; } public void setIssuerId(String issuerId) { this.issuerId = issuerId; } } 


SalesforceSAMLResponseGenerator.java:
 public class SalesforceSAMLResponseGenerator extends SAMLResponseGenerator { private static final String SALESFORCE_LOGIN_URL = "https://login.salesforce.com"; private static final String SALESFORCE_AUDIENCE_URI = "https://saml.salesforce.com"; private static final Logger logger = Logger.getLogger(SalesforceSAMLResponseGenerator.class); private static final int maxSessionTimeoutInMinutes = 10; private String nameId; public SalesforceSAMLResponseGenerator(X509Certificate certificate, PublicKey publicKey, PrivateKey privateKey, String issuerId, String nameId) { super(certificate, publicKey, privateKey, issuerId); this.nameId = nameId; } @Override protected Assertion buildAssertion() { try { // Create the NameIdentifier NameID nameId = buildXMLObject(NameID.DEFAULT_ELEMENT_NAME); nameId.setValue(this.nameId); nameId.setFormat(NameID.EMAIL); // Create the SubjectConfirmation SubjectConfirmationData confirmationMethod = buildXMLObject(SubjectConfirmationData.DEFAULT_ELEMENT_NAME); DateTime notBefore = new DateTime(); DateTime notOnOrAfter = notBefore.plusMinutes(maxSessionTimeoutInMinutes); confirmationMethod.setNotOnOrAfter(notOnOrAfter); confirmationMethod.setRecipient(SALESFORCE_LOGIN_URL); SubjectConfirmation subjectConfirmation = buildXMLObject(SubjectConfirmation.DEFAULT_ELEMENT_NAME); subjectConfirmation.setMethod(SubjectConfirmation.METHOD_BEARER); subjectConfirmation.setSubjectConfirmationData(confirmationMethod); // Create the Subject Subject subject = buildXMLObject(Subject.DEFAULT_ELEMENT_NAME); subject.setNameID(nameId); subject.getSubjectConfirmations().add(subjectConfirmation); // Create Authentication Statement AuthnStatement authnStatement = buildXMLObject(AuthnStatement.DEFAULT_ELEMENT_NAME); DateTime now2 = new DateTime(); authnStatement.setAuthnInstant(now2); authnStatement.setSessionNotOnOrAfter(now2.plus(maxSessionTimeoutInMinutes)); AuthnContext authnContext = buildXMLObject(AuthnContext.DEFAULT_ELEMENT_NAME); AuthnContextClassRef authnContextClassRef = buildXMLObject(AuthnContextClassRef.DEFAULT_ELEMENT_NAME); authnContextClassRef.setAuthnContextClassRef(AuthnContext.UNSPECIFIED_AUTHN_CTX); authnContext.setAuthnContextClassRef(authnContextClassRef); authnStatement.setAuthnContext(authnContext); Audience audience = buildXMLObject(Audience.DEFAULT_ELEMENT_NAME); audience.setAudienceURI(SALESFORCE_AUDIENCE_URI); AudienceRestriction audienceRestriction = buildXMLObject(AudienceRestriction.DEFAULT_ELEMENT_NAME); audienceRestriction.getAudiences().add(audience); Conditions conditions = buildXMLObject(Conditions.DEFAULT_ELEMENT_NAME); conditions.setNotBefore(notBefore); conditions.setNotOnOrAfter(notOnOrAfter); conditions.getConditions().add(audienceRestriction); // Create Issuer Issuer issuer = (Issuer) buildXMLObject(Issuer.DEFAULT_ELEMENT_NAME); issuer.setValue(getIssuerId()); // Create the assertion Assertion assertion = buildXMLObject(Assertion.DEFAULT_ELEMENT_NAME); assertion.setIssuer(issuer); assertion.setID(UUID.randomUUID().toString()); assertion.setIssueInstant(notBefore); assertion.setVersion(SAMLVersion.VERSION_20); assertion.getAuthnStatements().add(authnStatement); assertion.setConditions(conditions); assertion.setSubject(subject); return assertion; } catch (ConfigurationException e) { logger.error(e, e); } return null; } } 


TestSSO.java:
 public class TestSSO { private PrivateKey privateKey; private X509Certificate certificate; public void readCertificate(InputStream inputStream, String alias, String password) throws NoSuchAlgorithmException, CertificateException, IOException, UnrecoverableKeyException, KeyStoreException { KeyStore keyStore = KeyStore.getInstance("JKS"); keyStore.load(inputStream, password.toCharArray()); Key key = keyStore.getKey(alias, password.toCharArray()); if (key == null) { throw new RuntimeException("Got null key from keystore!"); } privateKey = (PrivateKey) key; certificate = (X509Certificate) keyStore.getCertificate(alias); if (certificate == null) { throw new RuntimeException("Got null cert from keystore!"); } } public void run() throws ConfigurationException, UnrecoverableKeyException, InvalidKeyException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, KeyStoreException, NoSuchProviderException, SignatureException, IOException, org.opensaml.xml.signature.SignatureException, URISyntaxException, UnmarshallingException, MarshallingException { String strIssuer = "Eugene Burtsev"; String strNameID = "user@test.com"; InputStream inputStream = TestSSO.class.getResourceAsStream("/keystore"); readCertificate(inputStream, "SSO", "12345678"); SAMLResponseGenerator responseGenerator = new SalesforceSAMLResponseGenerator(certificate, certificate.getPublicKey(), privateKey, strIssuer, strNameID); String samlAssertion = responseGenerator.generateSAMLAssertionString(); System.out.println(); System.out.println("Assertion String: " + samlAssertion); } public static void main(String[] args) throws ConfigurationException, UnrecoverableKeyException, InvalidKeyException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, KeyStoreException, NoSuchProviderException, SignatureException, IOException, org.opensaml.xml.signature.SignatureException, URISyntaxException, UnmarshallingException, MarshallingException { new TestSSO().run(); } } 


рд╕рддреНрдпрд╛рдкрдирдХрд░реНрддрд╛ рдХреЗ рд╕рднреА рдЖрд╢реНрд╡рд╛рд╕рдиреЛрдВ рдХреЗ рдмрд╛рд╡рдЬреВрдж рдХрд┐ рдХреЛрдб рдорд╛рдиреНрдп рд╣реИ, SSO рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ SalesForce рдХреЛ рдЕрдзрд┐рдХреГрдд рдХрд░рдирд╛ рдХреЛрдИ рддреБрдЪреНрдЫ рдХрд╛рд░реНрдп рдирд╣реАрдВ рдерд╛ред рдЙрдирдХреЗ рд╡рд┐рдХреА рд╕реЗ рд▓рдЧрднрдЧ рдПрдХ рджрд░реНрдЬрди рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ рдФрд░ рдЙрдирдореЗрдВ рд╕реЗ рдХрд┐рд╕реА рдиреЗ рднреА рдпрд╣ рдХрд╣рддреЗ рд╣реБрдП рдХрд╛рдо рдирд╣реАрдВ рдХрд┐рдпрд╛ рдХрд┐ рд╡реЗ "рдЕрдорд╛рдиреНрдп рджрд╛рд╡реЗ" рдХрд╣рддреЗ рд╣реИрдВ ... рдЗрд╕рд▓рд┐рдП рддреАрди рджрд┐рди рдмреАрдд рдЧрдП ... рдФрд░ рдлрд┐рд░ рдпрд╣ рдореБрдЭреЗ OASIS рд╡рд┐рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЛ рдкрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реБрдЖ, рдЬрд┐рд╕рдореЗрдВ рдкрд╡рд┐рддреНрд░ рдЬреНрдЮрд╛рди рд╕реАрдЦрд╛ рдЧрдпрд╛ рдерд╛: SAML рдХреА рдЬрд░реВрд░рдд рдереА "SAMLResponse" рдкреИрд░рд╛рдореАрдЯрд░ рдореЗрдВ POST рдЕрдиреБрд░реЛрдз рднреЗрдЬреЗрдВ ... рдЕрдм рд╕рдлрд▓рддрд╛ рдХреА рдЙрдореНрдореАрдж рдирд╣реАрдВ рд╣реИ, рдЗрд╕ рдЬреНрдЮрд╛рди рдХреЛ рд╡реНрдпрд╡рд╣рд╛рд░ рдореЗрдВ рд▓рд╛рдпрд╛ рдЧрдпрд╛ рдерд╛, рдФрд░ рдПрдХ рдЪрдорддреНрдХрд╛рд░ рд╣реБрдЖ - Salesforce рдиреЗ рд▓реЙрдЧрд┐рди рдХреЗ рд▓рд┐рдП рдПрдХ рдЯреЛрдХрди рдХреЗ рд╕рд╛рде рдПрдХ рд▓рд┐рдВрдХ рдЬрд╛рд░реА рдХрд┐рдпрд╛ред рдиреАрдЪреЗ рдПрдХ рдкреВрд░реНрдг рдЙрджрд╛рд╣рд░рдг рдХрд╛рд░реНрдпрдХреНрд░рдо рд╣реИ, рдЬреЛ рд╕реЗрд▓реНрд╕рдлреЛрд░реНрд╕ рдХреЗ рд▓рд┐рдП рдПрд╕рдПрд╕рдУ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд╣реА рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЛ рджрд░реНрд╢рд╛рддрд╛ рд╣реИред

 public class TestSSO { private static final Logger logger = Logger.getLogger(TestSSO.class); public static DefaultHttpClient getThreadSafeClient() { DefaultHttpClient client = new DefaultHttpClient(); ClientConnectionManager mgr = client.getConnectionManager(); HttpParams params = client.getParams(); client = new DefaultHttpClient(new ThreadSafeClientConnManager( mgr.getSchemeRegistry()), params); return client; } private static HttpClient createHttpClient() { HttpClient httpclient = getThreadSafeClient(); httpclient.getParams().setParameter( CoreProtocolPNames.PROTOCOL_VERSION, new ProtocolVersion("HTTP", 1, 1)); return httpclient; } private static void sendSamlRequest(String samlAssertion) { HttpClient httpClient = createHttpClient(); try { System.out.println(samlAssertion); HttpPost httpPost = new HttpPost("https://login.salesforce.com/"); MultipartEntity entity = new MultipartEntity(HttpMultipartMode.STRICT); entity.addPart("SAMLResponse", new StringBody(samlAssertion)); httpPost.setEntity(entity); HttpResponse httpResponse = httpClient.execute(httpPost); Header location = httpResponse.getFirstHeader("Location"); if (null != location) { System.out.println(location.getValue()); } } catch (Exception e) { logger.error(e, e); } finally { httpClient.getConnectionManager().shutdown(); } } private PrivateKey privateKey; private X509Certificate certificate; public void readCertificate(InputStream inputStream, String alias, String password) throws NoSuchAlgorithmException, CertificateException, IOException, UnrecoverableKeyException, KeyStoreException { KeyStore keyStore = KeyStore.getInstance("JKS"); keyStore.load(inputStream, password.toCharArray()); Key key = keyStore.getKey(alias, password.toCharArray()); if (key == null) { throw new RuntimeException("Got null key from keystore!"); } privateKey = (PrivateKey) key; certificate = (X509Certificate) keyStore.getCertificate(alias); if (certificate == null) { throw new RuntimeException("Got null cert from keystore!"); } } public void run() throws ConfigurationException, UnrecoverableKeyException, InvalidKeyException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, KeyStoreException, NoSuchProviderException, SignatureException, IOException, org.opensaml.xml.signature.SignatureException, URISyntaxException, UnmarshallingException, MarshallingException { String strIssuer = "Eugene Burtsev"; String strNameID = "user@test.com"; InputStream inputStream = TestSSO.class.getResourceAsStream("/keystore"); readCertificate(inputStream, "SSO", "12345678"); SAMLResponseGenerator responseGenerator = new SalesforceSAMLResponseGenerator(certificate, certificate.getPublicKey(), privateKey, strIssuer, strNameID); String samlAssertion = responseGenerator.generateSAMLAssertionString(); System.out.println(); System.out.println("Assertion String: " + samlAssertion); sendSamlRequest(Base64.encodeBase64String(samlAssertion.getBytes("UTF-8"))); } public static void main(String[] args) throws ConfigurationException, UnrecoverableKeyException, InvalidKeyException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, KeyStoreException, NoSuchProviderException, SignatureException, IOException, org.opensaml.xml.signature.SignatureException, URISyntaxException, UnmarshallingException, MarshallingException { new TestSSO().run(); } } 


рд╕реНрд░реЛрддреЛрдВ рдХреЗ рд╕рд╛рде рдкреБрд░рд╛рд▓реЗрдЦ рдпрд╣рд╛рдВ рд▓реЗ рдЬрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ
рдФрд░ рдЕрдВрдд рдореЗрдВ, рдиреИрддрд┐рдХрддрд╛: рдХрд┐рд╕реА рдкрд░ рднрд░реЛрд╕рд╛ рдордд рдХрд░реЛ, рдХреЗрд╡рд▓ рдЪрд╢реНрдорд╛ рд╕рдЪреНрдЪрд╛рдИ рдХреЛ рд▓реЗ рдЬрд╛рддрд╛ рд╣реИ!

рдЙрдкрдпреЛрдЧреА рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХреА рд╕реВрдЪреА:
  1. SAM.com рдХреЗ рд╕рд╛рде Force.com рдкрд░ рд╕рд┐рдВрдЧрд▓ рд╕рд╛рдЗрди-рдСрди
  2. docs.oasis-open.org/security/saml/v2.0/saml-bindings-2.0-os.pdf
  3. www.sslshopper.com/article-most-common-java-keytool-keystore-commands.html

Source: https://habr.com/ru/post/In151006/


All Articles