150 lines
6.7 KiB
Plaintext
150 lines
6.7 KiB
Plaintext
<cfinclude template="app_saml_config.cfm"/>
|
|
<!---<cfinclude template="saml.cfm"/>--->
|
|
|
|
<cfset ksFile = CreateObject("Java", "java.io.File").init(request.SAML.KEYSTORE_FILE_NAME) />
|
|
<cfset ksInputStream = CreateObject("Java", "java.io.FileInputStream").init(ksFile) />
|
|
<cfset keystore = CreateObject("Java" , "java.security.KeyStore").getInstance("JKS") />
|
|
<cfset keystore.load(ksInputStream, request.SAML.KEYSTORE_PASS.toCharArray()) />
|
|
<cfset certificate = keystore.getCertificate(request.SAML.CERTIFICATE_ALIAS) />
|
|
<cfset privateKey = keystore.getKey(request.SAML.CERTIFICATE_ALIAS, request.SAML.KEY_PASS.toCharArray()) />
|
|
<cfset signingCertString = binaryEncode(certificate.getEncoded(),"base64") />
|
|
<cfset encryptionCertString = signingCertString/>
|
|
|
|
<cfparam name="SAMLResponse"/>
|
|
<cfparam name="RelayState" default=""/>
|
|
|
|
<cfset SAMLResponseStr = ToString(ToBinary(SAMLResponse))/>
|
|
<cfset SAMLResponseXml = XMLParse(SAMLResponseStr)/><!---*** catch exception--->
|
|
<cfset SAMLStatus = XMLSearch(SAMLResponseXml, "//*[name()='samlp:StatusCode']")[1].XmlAttributes.Value/><!---*** catch exception--->
|
|
<cfset err=""/>
|
|
|
|
<cfscript>
|
|
/*
|
|
On Lucee
|
|
Error "Could not initialize class org.apache.xml.security.Init" is possibly caused by incompatible slf4j(api?)
|
|
Solution: put slf4j-api-1.7.22.jar to D:\lucee\tomcat\lib
|
|
*/
|
|
Init = CreateObject("Java", "org.apache.xml.security.Init").Init().init();
|
|
/*
|
|
// more complex way to initialize xmlsec
|
|
ref = createObject("java", "org.apache.xml.security.Init");
|
|
// writeDump(ref);
|
|
// initialize if needed
|
|
if (!ref.isInitialized()) {
|
|
// find static method named "init" with no parameters
|
|
method = ref.getClass().getDeclaredMethod("init", []);
|
|
// invoke it via reflection
|
|
method.invoke(ref, javacast("null", ""));
|
|
}
|
|
*/
|
|
dataArray=XMLSearch(SAMLResponseXml, "//*[name()='EncryptedAssertion']");
|
|
try {
|
|
dataElement=dataArray[1];
|
|
DECRYPT_MODE=CreateObject( "Java", "org.apache.xml.security.encryption.XMLCipher").DECRYPT_MODE;
|
|
cipher=CreateObject( "Java", "org.apache.xml.security.encryption.XMLCipher").getInstance();
|
|
cipher.init(DECRYPT_MODE, javacast("null", ""));
|
|
cipher.setKEK(privateKey);
|
|
cipher.doFinal(dataElement.getOwnerDocument(), dataElement, true);
|
|
} catch (any e) {
|
|
err = "Ошибка авторизации. Статус запроса: " & SAMLStatus;
|
|
}
|
|
|
|
|
|
//<!---проверка подписи--->
|
|
if (NOT len(err)) {
|
|
assertionArray = XMLSearch(SAMLResponseXml, "/*[name()='samlp:Response']/*[name()='EncryptedAssertion']/*[name()='Assertion']");
|
|
try {
|
|
assertionElement = assertionArray[1];
|
|
assertionElement.setIdAttribute("ID",true); //sic!
|
|
//WriteDump(assertionElement);
|
|
Init = CreateObject("Java", "org.apache.xml.security.Init").Init().init();
|
|
SignatureConstants = CreateObject("Java", "org.apache.xml.security.utils.Constants");
|
|
SignatureSpecNS = SignatureConstants.SignatureSpecNS; //writeDump(SignatureSpecNS);
|
|
xmlSignatureClass = CreateObject("Java", "org.apache.xml.security.signature.XMLSignature");
|
|
signatureElement=SAMLResponseXml.getElementsByTagNameNS(SignatureSpecNS,"Signature").item(0);
|
|
xmlSignature = xmlSignatureClass.init(signatureElement,"");
|
|
keyInfo = xmlSignature.getKeyInfo();
|
|
X509CertificateResolverCN = "org.apache.xml.security.keys.keyresolver.implementations.X509CertificateResolver";
|
|
keyResolver = CreateObject("Java", X509CertificateResolverCN).init();
|
|
keyInfo.registerInternalKeyResolver(keyResolver);
|
|
x509cert = keyInfo.getX509Certificate();
|
|
isValid = xmlSignature.checkSignatureValue(x509cert);
|
|
} catch (any e) {
|
|
err = "Ошибка при проверке подписи. Статус запроса: " & SAMLStatus;
|
|
}
|
|
}
|
|
|
|
</cfscript>
|
|
|
|
<cfif NOT len(err)>
|
|
<cfif (isValid NEQ 0)>
|
|
<cfset NameID=XMLSearch(SAMLResponseXml, "string(/*[name()='samlp:Response']/*[name()='EncryptedAssertion']/*[name()='Assertion']/*[name()='Subject']/*[name()='NameID'])") />
|
|
<cfset SessionIndex=XMLSearch(SAMLResponseXml, "string(//*[name()='Assertion']/*[name()='AuthnStatement']/@SessionIndex)") />
|
|
<cftry>
|
|
<cfset NotOnOrAfter=XMLSearch(SAMLResponseXml, "string(//*[name()='Assertion']/*[name()='Conditions']/@NotOnOrAfter)") />
|
|
<cfset SAML_IdPCredentialsExpirationTime=ParseDateTime(NotOnOrAfter)/>
|
|
<cfcatch type="ANY">
|
|
<cfset SAML_IdPCredentialsExpirationTime=Now()/>
|
|
</cfcatch>
|
|
</cftry>
|
|
|
|
<cfquery name="qUsr" datasource="#request.DS#">
|
|
select usr_id, locked, shortname
|
|
from usr
|
|
where login=<cfqueryparam cfsqltype="cf_sql_varchar" value="#NameID#">
|
|
</cfquery>
|
|
|
|
<cfif (qUsr.RecordCount NEQ 1)>
|
|
<cfset err="Пользователь #NameID# не зарегистрирован в данной системе."/>
|
|
<cfdump var=#SAMLResponseXml#/>
|
|
<cfset QueryAddRow(qUsr, 1)/>
|
|
<cfset qUsr.usr_id=request.GUEST_USR_ID/>
|
|
</cfif>
|
|
|
|
<cfif SAML_IdPCredentialsExpirationTime LE Now()>
|
|
<cfset err="Данные аутентификации устарели (были действительны до #dateFormat(SAML_IdPCredentialsExpirationTime,'DD.MM.YYYY')# #timeFormat(SAML_IdPCredentialsExpirationTime,'HH:MM')#). Пожалуйста, авторизуйтесь заново."/>
|
|
</cfif>
|
|
<cfelse>
|
|
<cfset err="Подпись SAML-ответа недействительна."/>
|
|
</cfif>
|
|
</cfif>
|
|
|
|
|
|
<cfif len(err)>
|
|
<cfoutput><span class="err">#err#</span></cfoutput>
|
|
<cfelse>
|
|
<cflock scope="session" type="exclusive" timeout="3">
|
|
<cfparam name="session.targetScriptName" default=""/>
|
|
<cfparam name="session.targetQueryString" default=""/>
|
|
<cfset session.SAML_NameID=#NameID#/>
|
|
<cfset session.SAML_SessionIndex=#SessionIndex#/>
|
|
<cfset session.SAML_IdPCredentialsExpirationTime=#SAML_IdPCredentialsExpirationTime#/>
|
|
<cfset session.usr_id=qUsr.usr_id/>
|
|
<cfset request.usr_id=qUsr.usr_id>
|
|
</cflock>
|
|
|
|
<!--- redirect to requested url --->
|
|
<cfset strUrl="../index.cfm"/>
|
|
<!--- <cfset strUrl="req.cfm"/> --->
|
|
<cfif len(RelayState) GT 0>
|
|
<cfset strUrl="../#RelayState#"/>
|
|
<cfelseif len(session.targetScriptName) GT 0>
|
|
<cfif NOT lCase(session.targetScriptName) EQ "login.cfm">
|
|
<cfset strUrl=#session.targetScriptName#>
|
|
<cfif len(session.targetQueryString) GT 0>
|
|
<cfif Find("?", "#strUrl#", 1) GT 0>
|
|
<cfset strUrl="../#strUrl#&#urlEncodedFormat(session.targetQueryString)#"/>
|
|
<cfelse>
|
|
<cfset strUrl="../#strUrl#?#urlEncodedFormat(session.targetQueryString)#"/>
|
|
</cfif>
|
|
</cfif>
|
|
<cfset session.targetScriptName="">
|
|
<cfset session.targetQueryString="">
|
|
</cfif>
|
|
</cfif>
|
|
<!--- <cfoutput>
|
|
<br><a href="#strUrl#">Аутентификация успешна. Продолжить работу как #qUsr.shortname#</a>
|
|
<br><pre>#saml.prettyPrintXml(SAMLResponseXml)#</pre>
|
|
</cfoutput> --->
|
|
<cflocation url="#strUrl#" addtoken="no"/>
|
|
</cfif> |