最近在工作中和海外一家公司对接单点登录,用到了SAML2.0协议,目前公司的单点登录
还是比较老的CASE3.5版本,不支持SAML2,要支持也要定制优,由于后面肯定是要升级,所
以不在源码上做调整支持,单独建了个SSO应用作为CASE客户端,并包装客户的接口,登录
还是用CASE认证。
由于客户没有完全实现SAML2.0(SP)的功能, IDP由我司CASE提供,我司SSO应用其实是半个SP的功能,提供给页面访问并认证,认证成功后response给客户,客户校验通过后才返回页面,
在这里插入图片描述

  1. 推荐一个很好的SAML工具,想测试一个SAML2的接口很容易,支持多种加密
    工具链接[https://www.samltool.com/generic_sso_res.php]

    Reponse各种示例SAML Response 各种示例签名工具:
    在这里插入图片描述

2.代码示例
下面是groovy代码,java类似

import org.springframework.boot.context.properties.ConfigurationProperties

@ConfigurationProperties(prefix = "sso")
class SSOProperties {
	
	String responseAdp

	String audienceAdp

	String relayStateAdp

	boolean testAdp

	String[] apps
}
@Service("adpService")
@Slf4j
@EnableConfigurationProperties([SSOProperties.class])
class AdpService implements SamlService{
 @Resource
    SSOProperties ssoProperties
    @Resource
    AccountService accountService
def getSamlResponse() {
        String username = AssertionHolder.getAssertion().getPrincipal().getName()
        log.info("username: ${username}")
        String jobNo = accountService.getJobNo(username)
        def model = [:]
        //签名消息
        def xml = signedResponse(jobNo)
        //返回页面form提交的参数
        model.put("samlResponse", Base64.encodeBytes(xml.getBytes()))
        model.put("relayState", ssoProperties.getRelayStateAdp())
        model.put("redirectUrl", ssoProperties.getResponseAdp())
        model
    }
def signedResponse(String userId){
        String destination = ssoProperties.getResponseAdp()
        final Response samlResponse = SamlHelper.buildResponse(UUIDFactory.INSTANCE.getUUID(), destination)
        DateTime notBefore =  new DateTime(2018, 10, 19, 1, 0, 0, 0, ISOChronology.getInstanceUTC())
        DateTime notOnOrAfter = new DateTime(2021, 10, 19, 1, 0, 0, 0, ISOChronology.getInstanceUTC())
        String audienceURI = ssoProperties.getAudienceAdp()
        Assertion assertion = SamlHelper.buildAssertion(samlResponse, userId,audienceURI,  notBefore, notOnOrAfter)
        AttributeStatement attributeStatement = SamlHelper.buildAttributeStatement("PersonImmutableID", userId)
        assertion.getAttributeStatements().add(attributeStatement)
        SamlHelper.signXMLObject(assertion)
        samlResponse.getAssertions().add(assertion)
        def xml = SamlHelper.buildXMLObjectToString(samlResponse)
        return xml
    }
 }
@Slf4j
abstract class SamlHelper {

    static final XMLObjectBuilderFactory builderFactory

    static {
        try {
            DefaultBootstrap.bootstrap()
        } catch (ConfigurationException e) {
            log.error(e.getMessage(), e)
        }
        Security.addProvider(new BouncyCastleProvider())
        builderFactory = Configuration.getBuilderFactory()
    }

    static String buildXMLObjectToString(XMLObject xmlObject) {
        Marshaller marshaller = Configuration.getMarshallerFactory().getMarshaller(xmlObject)
        Element authDOM
        try {
            authDOM = marshaller.marshall(xmlObject)
            StringWriter rspWrt = new StringWriter()
            XMLHelper.writeNode(authDOM, rspWrt)
            String messageXML = rspWrt.toString()
            return messageXML
        } catch (MarshallingException e) {
            throw new RuntimeException(e)
        }
    }

    static XMLObject buildStringToXMLObject(String xmlObjectString) {
        try {
            BasicParserPool parser = new BasicParserPool()
            parser.setNamespaceAware(true)
            String xmlString = decode64SAMLResponse(xmlObjectString)
            Document doc = (Document) parser.parse(new ByteArrayInputStream(xmlString.getBytes()))
            Element samlElement = (Element) doc.getDocumentElement()
            Unmarshaller unmarshaller = Configuration.getUnmarshallerFactory().getUnmarshaller(samlElement)
            return unmarshaller.unmarshall(samlElement)
        } catch (XMLParserException e) {
            throw new RuntimeException(e)
        } catch (UnmarshallingException e) {
            throw new RuntimeException(e)
        }
    }

    static AuthnRequest buildAuthnRequest(String ticket, String setAssertionConsumerServiceURL) {
        NameID nameid = (NameID) buildXMLObject(NameID.DEFAULT_ELEMENT_NAME)
        nameid.setFormat(NameID.UNSPECIFIED)
        nameid.setValue(ticket)
        Subject subject = (Subject) buildXMLObject(Subject.DEFAULT_ELEMENT_NAME)
        subject.setNameID(nameid)
        Audience audience = (Audience) buildXMLObject(Audience.DEFAULT_ELEMENT_NAME)
        audience.setAudienceURI(Constants.LOCALDOMAIN)
        AudienceRestriction ar = (AudienceRestriction) buildXMLObject(AudienceRestriction.DEFAULT_ELEMENT_NAME)
        ar.getAudiences().add(audience)
        Conditions conditions = (Conditions) buildXMLObject(Conditions.DEFAULT_ELEMENT_NAME)
        conditions.getAudienceRestrictions().add(ar)
        AuthnContextClassRef classRef = (AuthnContextClassRef) buildXMLObject(AuthnContextClassRef.DEFAULT_ELEMENT_NAME)
        classRef.setAuthnContextClassRef("urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport")
        RequestedAuthnContext rac = (RequestedAuthnContext) buildXMLObject(RequestedAuthnContext.DEFAULT_ELEMENT_NAME)
        rac.getAuthnContextClassRefs().add(classRef)
        AuthnRequest request = (AuthnRequest) buildXMLObject(AuthnRequest.DEFAULT_ELEMENT_NAME)
        request.setSubject(subject)
        request.setConditions(conditions)
        request.setRequestedAuthnContext(rac)
        request.setForceAuthn(false)
        request.setAssertionConsumerServiceURL(setAssertionConsumerServiceURL)
        request.setAttributeConsumingServiceIndex(0)
        request.setProviderName("IDP Provider")
        request.setID("_" + UUIDFactory.INSTANCE.getUUID())
        request.setVersion(SAMLVersion.VERSION_20)
        request.setIssueInstant(new DateTime(2005, 1, 31, 12, 0, 0, 0, ISOChronology.getInstanceUTC()))
        request.setDestination(Constants.LOCALDOMAIN)
        request.setConsent("urn:oasis:names:tc:SAML:2.0:consent:obtained")
        Issuer rIssuer = (Issuer) buildXMLObject(Issuer.DEFAULT_ELEMENT_NAME)
        rIssuer.setFormat("urn:oasis:names:tc:SAML:2.0:nameid-format:entity")
        rIssuer.setValue(Constants.LOCALDOMAIN)
        request.setIssuer(rIssuer)
        return request
    }

    static Response buildResponse(String requestId, String destination) {
        Response response = (Response) buildXMLObject(Response.DEFAULT_ELEMENT_NAME)
        Namespace namespace = new Namespace("urn:oasis:names:tc:SAML:2.0:assertion", "saml2")
        response.addNamespace(namespace)
        response.setID(UUIDFactory.INSTANCE.getUUID())
//        response.setInResponseTo(requestId)
        response.setDestination(destination)
        Calendar now = DateUtil.getUTCCalendar()
        response.setIssueInstant(new DateTime(now.get(Calendar.YEAR), (now.get(Calendar.MONTH) + 1), now.get(Calendar.DAY_OF_MONTH), now.get(Calendar.HOUR_OF_DAY), now.get(Calendar.MINUTE), now.get(Calendar.SECOND), 0, ISOChronology.getInstanceUTC()))
        Issuer rIssuer = (Issuer) buildXMLObject(Issuer.DEFAULT_ELEMENT_NAME)
        // rIssuer.setFormat("urn:oasis:names:tc:SAML:2.0:nameid-format:entity")
        rIssuer.setValue(Constants.ISSUER)
        rIssuer.removeNamespace(new Namespace("urn:oasis:names:tc:SAML:2.0:assertion", "saml2"))
        response.setIssuer(rIssuer)

        Status status = (Status) buildXMLObject(Status.DEFAULT_ELEMENT_NAME)
        StatusCode statusCode = (StatusCode) buildXMLObject(StatusCode.DEFAULT_ELEMENT_NAME)
        statusCode.setValue("urn:oasis:names:tc:SAML:2.0:status:Success")
        response.setStatus(status)
        status.setStatusCode(statusCode)
        return response
    }

    static Assertion buildAssertion(Response response, String nameIdValue, String audienceURI, DateTime notBefore, DateTime notOnOrAfter) {
        Calendar now = DateUtil.getUTCCalendar()
        Assertion assertion = (Assertion) buildXMLObject(Assertion.DEFAULT_ELEMENT_NAME)
        assertion.setID(UUIDFactory.INSTANCE.getUUID())
        assertion.setIssueInstant(new DateTime(now.get(Calendar.YEAR), (now.get(Calendar.MONTH) + 1), now.get(Calendar.DAY_OF_MONTH), now.get(Calendar.HOUR_OF_DAY), now.get(Calendar.MINUTE), now.get(Calendar.SECOND), ISOChronology.getInstanceUTC()))
//        assertion.removeNamespace(new Namespace("urn:oasis:names:tc:SAML:2.0:assertion", "saml2"))
        assertion.addNamespace(new Namespace("http://www.w3.org/2001/XMLSchema-instance", "xsi"))
        assertion.addNamespace(new Namespace("http://www.w3.org/2001/XMLSchema", "xs"))
        AuthnStatement authnStatement = (AuthnStatement) buildXMLObject(AuthnStatement.DEFAULT_ELEMENT_NAME)
        authnStatement.setAuthnInstant(new DateTime(now.get(Calendar.YEAR), (now.get(Calendar.MONTH) + 1), now.get(Calendar.DAY_OF_MONTH), now.get(Calendar.HOUR_OF_DAY), now.get(Calendar.MINUTE), now.get(Calendar.SECOND), ISOChronology.getInstanceUTC()))
        authnStatement.setSessionIndex(UUIDFactory.INSTANCE.getUUID())
        now.add(Calendar.MINUTE, 2)
        DateTime sessionNotOnOrAfter = new DateTime(now.get(Calendar.YEAR), (now.get(Calendar.MONTH) + 1), now.get(Calendar.DAY_OF_MONTH), now.get(Calendar.HOUR_OF_DAY), now.get(Calendar.MINUTE), now.get(Calendar.SECOND), ISOChronology.getInstanceUTC())
        authnStatement.setSessionNotOnOrAfter(sessionNotOnOrAfter)

        AuthnContext authnContext = (AuthnContext) buildXMLObject(AuthnContext.DEFAULT_ELEMENT_NAME)
        AuthnContextClassRef classRef = (AuthnContextClassRef) buildXMLObject(AuthnContextClassRef.DEFAULT_ELEMENT_NAME)
        classRef.setAuthnContextClassRef("urn:oasis:names:tc:SAML:2.0:ac:classes:Password")
        authnContext.setAuthnContextClassRef(classRef)
        authnStatement.setAuthnContext(authnContext)
        assertion.getAuthnStatements().add(authnStatement)

        Issuer aIssuer = (Issuer) buildXMLObject(Issuer.DEFAULT_ELEMENT_NAME)
//        aIssuer.setFormat("urn:oasis:names:tc:SAML:2.0:nameid-format:entity")
        aIssuer.setValue(Constants.ISSUER)
        assertion.setIssuer(aIssuer)

        Subject subject = (Subject) buildXMLObject(Subject.DEFAULT_ELEMENT_NAME)
        NameID nameID = (NameID) buildXMLObject(NameID.DEFAULT_ELEMENT_NAME)
        nameID.setFormat("urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified")
        nameID.setSPNameQualifier(audienceURI)
        nameID.setValue(nameIdValue)

        SubjectConfirmation subjectConfirmation = (SubjectConfirmation) buildXMLObject(SubjectConfirmation.DEFAULT_ELEMENT_NAME)
        subjectConfirmation.setMethod("urn:oasis:names:tc:SAML:2.0:cm:bearer")
        subject.setNameID(nameID)
        SubjectConfirmationData subjectConfirmationData = (SubjectConfirmationData) buildXMLObject(SubjectConfirmationData.DEFAULT_ELEMENT_NAME)
        subjectConfirmationData.setNotOnOrAfter(sessionNotOnOrAfter)
        subjectConfirmationData.setRecipient(response.getDestination())
//        subjectConfirmationData.setInResponseTo(response.getInResponseTo())
        subjectConfirmation.setSubjectConfirmationData(subjectConfirmationData)
        subject.getSubjectConfirmations().add(subjectConfirmation)
        assertion.setSubject(subject)

        Conditions conditions = (Conditions) buildXMLObject(Conditions.DEFAULT_ELEMENT_NAME)
        conditions.setNotBefore(notBefore)
        conditions.setNotOnOrAfter(notOnOrAfter)
        AudienceRestriction audienceRestriction = (AudienceRestriction) buildXMLObject(AudienceRestriction.DEFAULT_ELEMENT_NAME)
        Audience audience = (Audience) buildXMLObject(Audience.DEFAULT_ELEMENT_NAME)
        audience.setAudienceURI(audienceURI)
        audienceRestriction.getAudiences().add(audience)
        conditions.getAudienceRestrictions().add(audienceRestriction)
        assertion.setConditions(conditions)

        assertion
    }

    static void signXMLObject(SignableXMLObject signableXMLObject) {
        SignatureBuilder signatureBuilder = (SignatureBuilder) builderFactory.getBuilder(Signature.DEFAULT_ELEMENT_NAME)
        BasicCredential basicCredential = new BasicCredential()
        basicCredential.setPrivateKey(CertificateHelper.getRSAPrivateKey())
        Signature signature = signatureBuilder.buildObject()
        signature.setCanonicalizationAlgorithm(Constants.CANON_ALGORITHM)
        signature.setSignatureAlgorithm(Constants.SIGNATURE_METHOD)
        signature.setSigningCredential(basicCredential)
        signableXMLObject.setSignature(signature)
        MarshallerFactory marshallerFactory = Configuration.getMarshallerFactory()
        Marshaller marshaller = marshallerFactory.getMarshaller(signableXMLObject)
        try {
            marshaller.marshall(signableXMLObject)
            Signer.signObject(signature)
        } catch (MarshallingException e) {
            log.error(e.getMessage(), e)
            throw new RuntimeException("XML Marshalling failure")
        } catch (SignatureException e) {
            log.error(e.getMessage(), e)
            throw new RuntimeException("Signature failure")
        }
    }

    static Attribute buildStringAttribute(String name, String value) {
        Attribute attribute = (Attribute) buildXMLObject(Attribute.DEFAULT_ELEMENT_NAME)
        attribute.setName(name)
        attribute.setNameFormat("urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified")
        XMLObjectBuilder<?> stringBuilder = builderFactory.getBuilder(XSString.TYPE_NAME)
        XSString ldapAttribValue = (XSString) stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSString.TYPE_NAME)
        ldapAttribValue.removeNamespace(new Namespace("http://www.w3.org/2001/XMLSchema", "xs"))
        ldapAttribValue.setValue(value)
        attribute.getAttributeValues().add(ldapAttribValue)
        return attribute
    }

    static AttributeStatement buildAttributeStatement() {
        return (AttributeStatement) buildXMLObject(AttributeStatement.DEFAULT_ELEMENT_NAME)
    }

    static AttributeStatement buildAttributeStatement(String name, String value) {
        AttributeStatement attributeStatement = buildAttributeStatement()
        Attribute attribute = buildStringAttribute(name, value)
        attributeStatement.getAttributes().add(attribute)
        attributeStatement
    }

    static String buildArtifactResolve(Artifact artifact) {
        ArtifactResolve artifactResolve = (ArtifactResolve) buildXMLObject(ArtifactResolve.DEFAULT_ELEMENT_NAME)
        artifactResolve.setArtifact(artifact)
        return buildXMLObjectToString(artifactResolve)
    }

    static SSODescriptor buildSSODescriptor(String xmlFilePath, Class<?> descriptorType) {
        EntityDescriptor entityDescriptor = (EntityDescriptor) unmarshallElementWithXMLFile(xmlFilePath)
        if (descriptorType.getClass().getName().equals(IDPSSODescriptor.class.getName())) {
            return entityDescriptor.getIDPSSODescriptor("urn:oasis:names:tc:SAML:2.0:protocol")
        }
        return entityDescriptor.getSPSSODescriptor("urn:oasis:names:tc:SAML:2.0:protocol")
    }

    static X509Certificate getX509Certificate(String xmlFilePath) {
        SSODescriptor _SPSSODescriptor = buildSSODescriptor(xmlFilePath, SPSSODescriptor.class)
        List<KeyDescriptor> keyDescriptors = _SPSSODescriptor.getKeyDescriptors()
        KeyDescriptor keyDescriptor = keyDescriptors.get(0)
        KeyInfo keyInfo = keyDescriptor.getKeyInfo()
        List<X509Data> x509Datas = keyInfo.getX509Datas()
        List<X509Certificate> x509Certificates = x509Datas.get(0).getX509Certificates()
        X509Certificate x509Certificate = x509Certificates.get(0)
        return x509Certificate
    }

    static String decode64SAMLResponse(String samlResponse) {
        byte[] decodedBytes = Base64.decode(samlResponse)
        return new String(decodedBytes)
    }

    static def buildXMLObject(QName objectQName) {
        XMLObjectBuilder<?> builder = Configuration.getBuilderFactory().getBuilder(objectQName)
        return builder.buildObject(objectQName.getNamespaceURI(), objectQName.getLocalPart(), objectQName.getPrefix())
    }

    static XMLObject unmarshallElementWithXMLFile(String elementFile) {
        try {
            BasicParserPool parser = new BasicParserPool()
            parser.setNamespaceAware(true)
            Document doc = parser.parse(SamlHelper.class.getResourceAsStream(elementFile))
            Element samlElement = doc.getDocumentElement()
            Unmarshaller unmarshaller = Configuration.getUnmarshallerFactory().getUnmarshaller(samlElement)
            return unmarshaller.unmarshall(samlElement)
        } catch (XMLParserException e) {
            throw new RuntimeException(e)
        } catch (UnmarshallingException e) {
            throw new RuntimeException(e)
        }
    }

    /**
     * 加密断言
     * @param assertion
     * @param receiverCredential
     * @return
     */
    static EncryptedAssertion encrypt(Assertion assertion, X509Credential receiverCredential) {
        Credential symmetricCredential
        EncryptedAssertion encrypted = null
        try {
            symmetricCredential = SecurityHelper.getSimpleCredential(SecurityHelper.generateSymmetricKey(EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES128))
            EncryptionParameters encParams = new EncryptionParameters()
            encParams.setAlgorithm(EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES128)
            encParams.setEncryptionCredential(symmetricCredential)
            KeyEncryptionParameters kek = new KeyEncryptionParameters()
            kek.setAlgorithm(EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSA15)
            kek.setEncryptionCredential(receiverCredential)
            Encrypter encrypter = new Encrypter(encParams, kek)
            encrypter.setKeyPlacement(KeyPlacement.INLINE)
            encrypted = encrypter.encrypt(assertion)
        } catch (NoSuchAlgorithmException | KeyException e) {
            log.error(e.getMessage(), e)
        } catch (EncryptionException e) {
            log.error(e.getMessage(), e)
        }
        return encrypted
    }

    /**
     * 解密断言
     * @param enc
     * @param credential
     * @param federationMetadata
     * @return
     */
    static Assertion decrypt(EncryptedAssertion enc, Credential credential, String federationMetadata) {
        KeyInfoCredentialResolver keyResolver = new StaticKeyInfoCredentialResolver(credential)
        EncryptedKey key = enc.getEncryptedData().getKeyInfo().getEncryptedKeys().get(0)
        Decrypter decrypter = new Decrypter(null, keyResolver, new InlineEncryptedKeyResolver())
        decrypter.setRootInNewDocument(true)
        SecretKey dkey
        Assertion assertion = null
        try {
            dkey = (SecretKey) decrypter.decryptKey(key, enc.getEncryptedData().getEncryptionMethod().getAlgorithm())
            Credential shared = SecurityHelper.getSimpleCredential(dkey)
            decrypter = new Decrypter(new StaticKeyInfoCredentialResolver(shared), null, null)
            decrypter.setRootInNewDocument(true)
            assertion = decrypter.decrypt(enc)
        } catch (DecryptionException e) {
            log.error(e.getMessage(), e)
        }
        return assertion
    }

    /**
     * 签名断言
     * @param enc
     * @param credential
     * @param federationMetadata
     * @return
     */
    static Signature signature() {
        SignatureBuilder signatureBuilder = (SignatureBuilder) builderFactory.getBuilder(Signature.DEFAULT_ELEMENT_NAME)
        BasicCredential basicCredential = new BasicCredential()
        Signature signature = signatureBuilder.buildObject()
        basicCredential.setPrivateKey(CertificateHelper.getRSAPrivateKey())
        signature.setCanonicalizationAlgorithm(Constants.CANON_ALGORITHM)
        signature.setSignatureAlgorithm(Constants.SIGNATURE_METHOD)
        return signature
    }

    /**
     * 验签断言
     * @param enc
     * @param credential
     * @param federationMetadata
     * @return
     */
    static boolean validate(String base64Response) {
        SignableXMLObject signableXMLObject = (SignableXMLObject) buildStringToXMLObject(base64Response)
        return validate(signableXMLObject)
    }

    static boolean validate(SignableXMLObject signableXMLObject) {
        BasicCredential basicCredential = new BasicCredential()
        basicCredential.setPublicKey(CertificateHelper.getRSAPublicKey())
        SignatureValidator signatureValidator = new SignatureValidator(basicCredential)
        Signature signature = signableXMLObject.getSignature()
        try {
            signatureValidator.validate(signature)
            return true
        } catch (ValidationException e) {
            log.warn("验证签名错误" + e.getMessage())
            return false
        }
    }

    static Artifact buildArtifact() {
        String artifactId = UUIDFactory.INSTANCE.getUUID()
        Artifact artifact = (Artifact) buildXMLObject(Artifact.DEFAULT_ELEMENT_NAME)
        artifact.setArtifact(artifactId)
        return artifact
    }

    static ArtifactResolve buildArtifactResolve() {
        String artifactResolveId = UUIDFactory.INSTANCE.getUUID()
        ArtifactResolve artifactResolve = (ArtifactResolve) buildXMLObject(ArtifactResolve.DEFAULT_ELEMENT_NAME)
        artifactResolve.setID(artifactResolveId)
        Issuer aIssuer = (Issuer) buildXMLObject(Issuer.DEFAULT_ELEMENT_NAME)
        aIssuer.setFormat("urn:oasis:names:tc:SAML:2.0:nameid-format:entity")
        aIssuer.setValue(Constants.LOCALDOMAIN)
        artifactResolve.setIssuer(aIssuer)
        artifactResolve.setVersion(SAMLVersion.VERSION_20)
//        artifactResolve.setDestination(Constants.SP_ARTIFACT_RESOLUTION_SERVICE)
        artifactResolve.setIssueInstant(new DateTime(2005, 1, 31, 12, 0, 0, 0, ISOChronology.getInstanceUTC()))
        return artifactResolve
    }

    static ArtifactResponse buildArtifactResponse() {
        String artifactResponseId = UUIDFactory.INSTANCE.getUUID()
        ArtifactResponse artifactResponse = (ArtifactResponse) buildXMLObject(ArtifactResponse.DEFAULT_ELEMENT_NAME)
        artifactResponse.setID(artifactResponseId)
        artifactResponse.setVersion(SAMLVersion.VERSION_20)
        artifactResponse.setIssueInstant(new DateTime(2005, 1, 31, 12, 0, 0, 0, ISOChronology.getInstanceUTC()))
        return artifactResponse
    }

    static AttributeQuery buildAttributeQuery() {
        AttributeQuery attributeQuery = (AttributeQuery) buildXMLObject(AttributeQuery.DEFAULT_ELEMENT_NAME)
        return attributeQuery
    }

    static Status getStatusCode(boolean success) {
        Status status = (Status) buildXMLObject(Status.DEFAULT_ELEMENT_NAME)
        StatusCode statusCode = (StatusCode) buildXMLObject(StatusCode.DEFAULT_ELEMENT_NAME)
        statusCode.setValue(success ? StatusCode.SUCCESS_URI : StatusCode.AUTHN_FAILED_URI)
        status.setStatusCode(statusCode)
        return status
    }

}

页面部分代码

<form id="myForm" method="POST" th:action="${redirectUrl}">
    <input type="hidden" name="SAMLResponse" th:value="${samlResponse}" />
    <input type="hidden" name="RelayState" th:value="${relayState}" />
    <input type="submit" hidden value="Submit" />

</form>
</body>
<script type="text/javascript" th:inline="javascript">
    window. function(){
        document.getElementById('myForm').submit();
    }

</script>

POM.xml部分

<!-- case -->
		<dependency>
			<groupId>net.unicon.cas</groupId>
			<artifactId>cas-client-autoconfig-support</artifactId>
			<version>1.5.0-GA</version>
		</dependency>
		<!-- case -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-web</artifactId>
		</dependency>
		<!-- spring boot -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>fluent-hc</artifactId>
			<version>4.3.6</version>
		</dependency>
		<dependency>
			<groupId>commons-httpclient</groupId>
			<artifactId>commons-httpclient</artifactId>
			<version>3.1</version>
		</dependency>
		<dependency>
			<groupId>org.opensaml</groupId>
			<artifactId>opensaml</artifactId>
			<version>2.6.4</version>
		</dependency>
Logo

Authing 是一款以开发者为中心的全场景身份云产品,集成了所有主流身份认证协议,为企业和开发者提供完善安全的用户认证和访问管理服务

更多推荐