使用ColdFusion为单点登录数据
我为此帖子的长度提前道歉。 我对这个问题的真正了解还不够充分,以确定具体的问题实际上可能是什么! 但无论如何,我们一直在使用我们的会员API进行调用,以查询有关我们会员的信息(加入日期,会员类型等),使用@Leigh提供的步骤和建议,他们一直在努力! 再次感谢Leigh,我们的成员非常高兴能够做到这一点!
现在,我想为我们的会员设置单一登录,允许他们登录我们的页面,然后将其登录到他们的会员资料中,并已登录该网站。 根据API文档,我需要做的一件事是:
“使用签名证书签署登录人员的Portal用户名。”
我完全停留在这个上面。 我已经在表单中提供了一个XML私钥(由他们的.NET应用程序生成)
<RSAKeyValue><Modulus>{stuff}</Modulus><Exponent>{stuff}</Exponent><P>... etc etc
我收集到我无法直接使用此格式,必须将其转换为PEM格式或类似格式。 使用OpenSSL,我想我已经完成了这个工作,现在有一个格式为“----- BEGIN PRIVATE KEY ----- {stuff} ----- END PRIVATE KEY -----”的文件。
使用Leigh的解决方案确实给了我一个签名,但它与API文档中提供的示例不匹配。 我认为这是因为它使用HmacSHA1,而他们注意到“标题中的签名使用HMAC SHA1,而创建安全令牌的签名使用公钥/私钥对和RSA-SHA1。同样的方法不能用于生成两者。 “ 我试着改变
<cfset key = key.init(jKey,"HmacSHA1") />
至
<cfset key = key.init(jKey,"RSA-SHA1") />
并得到“算法RSA-SHA1不可用”。
我试图复制和粘贴其他一些建议的解决方案,但都没有工作。 一个例子(从12Robots.com得到):
<!--- Create a Java Cipher object and get a mode --->
<cfset cipher = createObject('java', 'javax.crypto.Cipher').getInstance("RSA") />
<!--- The mode tells the Cipher whether is will be encrypting or decrypting --->
<cfset encMode = cipher.ENCRYPT_MODE />
<cfset encryptedValue = "" /> <!--- Return variable --->
<!--- Initialize the Cipher with the mode and the key --->
<cfset cipher.init(encMode, key) />
<!--- Convert the string to bytes --->
<cfset stringBytes = stringToSign.getBytes("UTF8") />
<!--- Perform encryption --->
<cfset encryptedValue = cipher.doFinal(stringBytes, 0, len(inputString)) />
<cfdump var="#encryptedValue#">
这个实例中的“Key”是我前面提到的PEM文本,“stringToSign”是用户名。 我得到的错误是“无法使用指定方法名称和参数类型的方法,或者init方法被ColdFusion无法可靠解密的参数类型重载,ColdFusion找到了与提供的参数相匹配的0个方法如果这是一个Java对象并验证了该方法存在,请使用Javacast函数来减少歧义。“
我尝试过的另一件事是:
<cfset rsaPrivateKey = toBase64(key, "utf-8")>
<cfset jKey = JavaCast("string", rsaPrivateKey)>
<cfset jMsg = JavaCast("string", stringToSign).getBytes("ASCII")>
<cfset key = createObject("java", "java.security.PrivateKey")>
<cfset keySpec = createObject("java", "java.security.spec.PKCS8EncodedKeySpec")>
<cfset keyFactory = createObject("java", "java.security.KeyFactory")>
<cfset b64dec = createObject("java", "sun.misc.BASE64Decoder")>
<cfset sig = createObject("java", "java.security.Signature")>
<cfset byteClass = createObject("java", "java.lang.Class")>
<cfset byteArray = createObject("java", "java.lang.reflect.Array")>
<cfset byteClass = byteClass.forName(JavaCast("string", "java.lang.Byte"))>
<cfset keyBytes = byteArray.newInstance(byteClass, JavaCast("int", "1024"))>
<cfset keyBytes = b64dec.decodeBuffer(jKey)>
<cfset sig = sig.getInstance("SHA1withRSA", "SunJSSE")>
<cfset sig.initSign(keyFactory.getInstance("RSA").generatePrivate(keySpec.init(keyBytes)))>
<cfset sig.update(jMsg)>
<cfset signBytes = sig.sign()>
<cfset finalSig = ToBase64(signBytes)>
<cfdump var="#finalSig#">
这给了我“java.security.InvalidKeyException:无效的密钥格式。” 顺便说一句,如果我设置rsaPrivateKey只是“键”我得到一个不同的错误,“java.security.InvalidKeyException:IOException:DerInputStream.getLength():lengthTag = 127,太大。” 我很高兴得到不同的错误信息; 至少发生了一些事情! :-)
再次,我不知道这些Java函数在做什么。 我当然不明白为什么看似简单的事情变得如此复杂! 但是我的怀疑是,我不正确地存储私钥PEM,或者不正确地读出数据库(或两者),这就是导致这些不同解决方案失败的原因。 但是,我不确定是否可以肯定地说。
我欢迎任何有助于我的见解或建议! 如果有人需要更多信息,我很乐意提供。 非常感谢您提前!
我收集到我无法直接使用此格式,必须将其转换为PEM格式或类似格式
这样做没有错,但它不是技术上的要求。 关键信息可以从PEM文件或直接从XML加载。
选项1:从XML加载密钥:
将示例XML字符串解析为对象。 然后提取模数和私有指数(即<D>
元素)。 使用模数和指数来创建RSAPrivateKeySpec并加载RSA私钥:
xmlKeyString = "<RSAKeyValue><Modulus>........</D></RSAKeyValue>";
xmlDoc = xmlParse(xmlKeyString);
modBytes = binaryDecode(xmlDoc.RSAKeyValue.Modulus.xmlText, "base64");
dBytes = binaryDecode(xmlDoc.RSAKeyValue.D.xmlText, "base64");
modulus = createObject("java","java.math.BigInteger").init(1, modBytes);
exponent = createObject("java","java.math.BigInteger").init(1, dBytes);
keySpec = createObject("java", "java.security.spec.RSAPrivateKeySpec").init(modulus, exponent);
keyFactory = createObject("java", "java.security.KeyFactory").getInstance("RSA");
privateKey = keyFactory.generatePrivate(keySpec);
选项2:从PEM文件加载密钥:
将PEM文件读入一个变量。 删除标题/预告片,即“--- BEGIN / END RSA PRIVATE KEY -----”。 然后解码base64内容并使用KeyFactory加载私钥:
rawKey = replace( pemContent, "-----BEGIN RSA PRIVATE KEY-----", "" );
rawKey = replace( rawKey, "-----END RSA PRIVATE KEY-----", "" );
keyBytes = rawKey.trim().binaryDecode("base64");
keySpec = createObject("java", "java.security.spec.PKCS8EncodedKeySpec");
keyFactory = createObject("java", "java.security.KeyFactory").getInstance("RSA");
privateKey = keyFactory.generatePrivate(keySpec.init(keyBytes));
加载私钥后,可以使用Signature对象执行SHA1哈希并使用RSA密钥生成签名:
stringToSign = "test@membersuite.com";
signer = createObject("java", "java.security.Signature").getInstance("SHA1withRSA");;
signer.initSign(privateKey);
signer.update( stringToSign.getBytes("us-ASCII"));
signedBytes = binaryEncode(signer.sign(), "base64");
writeDump(signedBytes);
结果 (使用示例XML):
jTDKoH+INi19kGWn7WRk/PZegLv/9fPUOluaM57x8y1tkuwxOiyX86gxsZ7gU/OsStIT9Q5SVSG5NoaL3B+AxjuLY8b7XBMfTXHv2vidrDkkTTBW0D2LsrkZ3xzmvvPqqfA3tF2HXUYF+zoiTsr3bQdA32CJ+lDNkf+QjV3ZEoc=
注意:无论您选择哪种方法,正确保护私钥都非常重要。 一旦你有了样本的工作,一定要阅读如何最好地存储和保护私钥。
链接地址: http://www.djcxy.com/p/37231.html