initial draft
This commit is contained in:
+150
@@ -0,0 +1,150 @@
|
||||
<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>
|
||||
Reference in New Issue
Block a user