今年年初我发布了这个问题:Orbeon Single sign-on to SAP Netweaver
经过几个月的其他工作后,我再次看了一眼并接受了Orbeons的建议并开始调试Scala代码。
这一切都是用CE源格式github(4.4CE)完成的。 我看到的文件是Connection.scala https://github.com/orbeon/orbeon-forms/blob/master/src/main/scala/org/orbeon/oxf/util/Connection.scala
首先要注意的是,SAP Netweaver AS处理的sessionid与Tomcat略有不同。 sessionid和JSESSIONID不一样。正如前一篇文章所示,sessionid是JSESSIONID的较短版本,在Tomcat中它们是相同的。
让我们看一下sessionCookieFromIncoming方法(537): 在这个方法中,我发现了Netweaver的第一个问题:
def requestedSessionIdMatches =
Option(externalContext.getSession(false)) exists { session ⇒
val requestedSessionId = externalContext.getRequest.getRequestedSessionId
session.getId == requestedSessionId
}
val cookies = Option(nativeRequest.getCookies) getOrElse Array.empty[Cookie]
if (requestedSessionIdMatches && cookies.nonEmpty) {
代码行:
session.getId == requestedSessionId
这些在Netweaver上是不一样的(就像我在会话中说的是JSESSIONID的较短版本)。 所以我对修复的第一个想法就是这个(我不是Scala程序员所以请原谅一些不好的代码):
requestedSessionId contains session.getId
为了调试我添加了一些额外的代码。我从来没有启用调试,所以我只是把所有调试都放在控制台上 同样的方法
val pairsToForward =
for {
cookie ← cookies
if cookiesToForward.contains(cookie.getName)
} yield
cookie.getName + '=' + cookie.getValue
if (pairsToForward.nonEmpty) {
// Multiple cookies in the header, separated with ";"
val cookieHeaderValue = pairsToForward mkString "; "
debug("forwarding cookies", Seq(
"cookie" → cookieHeaderValue,
"requested session id" → externalContext.getRequest.getRequestedSessionId))
System.out.println("\nForwarding cookies " + "cookie " → cookieHeaderValue + "\nRequested session id " → externalContext.getRequest.getRequestedSessionId)
Some("cookie" → Array(cookieHeaderValue))
控制台输出:
forwarding cookies (cookie , MYSAPSSO2=AjExMDAgABBwb3J0YWw6ZV9nYW1zbTAxiAAHZGVmYXVsdAEACUVfR0FNU00wMQIAAzAwMAMAA1NQRAQADDIwMTMxMTMwMjEyMAUABAAAAAgKAAlFX0dBTVNNMDH%2FAQYwggECBgkqhkiG9w0BBwKggfQwgfECAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHATGB0TCBzgIBATAkMBsxCzAJBgNVBAYTAk5MMQwwCgYDVQQDEwNTUEQCBQCEogh2MAkGBSsOAwIaBQCgXTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0xMzExMzAyMTIwMzdaMCMGCSqGSIb3DQEJBDEWBBSryP8YWrWBPrzQBMyIypyfgGJT2TAJBgcqhkjOOAQDBC4wLAIUaMRLpG%2FxZYhzRIbyXzibMJJIGNcCFF4mmIESPh9o7kd7k46NNkr9ESLg;
JSESSIONID=TCaFUY3kaqppP-IakFa0KDRgeOKqQgGScngA_SAP158n6gVEgGH7sItNCAOyfIFO)(
Requested session id ,TCaFUY3kaqppP-IakFa0KDRgeOKqQgGScngA_SAP158n6gVEgGH7sItNCAOyfIFO)
看起来不错。我得到了我的SSO cookie和JSESSIONID的正确长度
有一些调试功能,但我将它们转储到控制台 请参阅代码行523. sessionID和传入会话cookie(JSESSIONID)之间的区别很明显 结果如下:
Debug sessie:(
new session,false)(
session id,TCaFUY3kaqppP-IakFa0KDRgeOKqQgGScngA_SAP)(
requested session id,TCaFUY3kaqppP-IakFa0KDRgeOKqQgGScngA_SAP158n6gVEgGH7sItNCAOyfIFO)(
session cookie name,JSESSIONID)(
incoming session cookies,TCaFUY3kaqppP-IakFa0KDRgeOKqQgGScngA_SAP158n6gVEgGH7sItNCAOyfIFO)(
incoming session headers,saplb_*=(J2EE7893620)7893650; MYSAPSSO2=AjExMDAgABBwb3J0YWw6ZV9nYW1zbTAxiAAHZGVmYXVsdAEACUVfR0FNU00wMQIAAzAwMAMAA1NQRAQADDIwMTMxMTMwMjEyMAUABAAAAAgKAAlFX0dBTVNNMDH%2FAQYwggECBgkqhkiG9w0BBwKggfQwgfECAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHATGB0TCBzgIBATAkMBsxCzAJBgNVBAYTAk5MMQwwCgYDVQQDEwNTUEQCBQCEogh2MAkGBSsOAwIaBQCgXTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0xMzExMzAyMTIwMzdaMCMGCSqGSIb3DQEJBDEWBBSryP8YWrWBPrzQBMyIypyfgGJT2TAJBgcqhkjOOAQDBC4wLAIUaMRLpG%2FxZYhzRIbyXzibMJJIGNcCFF4mmIESPh9o7kd7k46NNkr9ESLg; JSESSIONID=TCaFUY3kaqppP-IakFa0KDRgeOKqQgGScngA_SAP158n6gVEgGH7sItNCAOyfIFO)
返回def buildConnectionHeaders(398)。在方法结束时,Orbeon使用转发cookie构建一个新标头(我希望这是正确的。)
headersToForwardLowercase.toMap ++ explicitHeadersLowercase ++ newCookieHeader ++ tokenHeader
所以在newCookieHeader中应该是MYSAPSSO2 cookie和有效的JSESSIONID
要检查我是否添加了此代码: 来自Orbeon的代码(441):
val newCookieHeader = credentials match {
case None ⇒ sessionCookieHeader(externalContext)
case Some(_) ⇒ None
}
要打印这个值,我添加了这行代码:
var map = newCookieHeader.toMap
println(map("cookie")(0));
令我惊讶的是,控制台向我展示了这一点:
JSESSIONID=TCaFUY3kaqppP-IakFa0KDRgeOKqQgGScngA_SAP
不是我真正希望的。那怎么可能呢?这里和中间没有任何幻想。我知道该值不是来自sessionCookieFromGuess方法,因为显示正确值的print语句位于sessionCookieFromIncoming中。
所以我开始讨厌并想出了这个(再次不是Scala代码的最佳示例)。我在
之前将此代码添加到buildConnectionHeaders方法中 // Don't forward headers for which a value is explicitly passed by the caller, so start with headersToForward
// New cookie header, if present, overrides any existing cookies
headersToForwardLowercase.toMap ++ explicitHeadersLowercase ++ newCookieHeader ++ tokenHeader
我的代码。我从Orbeon代码中取出一些碎片并粘贴它们。然后我从externalContext中获取JSESSIONID和MYSAPSSO2并构建我自己的newCookieHeader
val requestOption = Option(externalContext.getRequest)
val nativeRequestOption =
requestOption flatMap
(r ⇒ Option(r.getNativeRequest)) collect
{ case r: HttpServletRequest ⇒ r }
val MYSAP =
for {
nativeRequest ← nativeRequestOption.toList
cookies ← Option(nativeRequest.getCookies).toList
cookie ← cookies
if cookie.getName == "MYSAPSSO2"
} yield
cookie.getValue
val MYJS =
for {
nativeRequest ← nativeRequestOption.toList
cookies ← Option(nativeRequest.getCookies).toList
cookie ← cookies
if cookie.getName == "JSESSIONID"
} yield
cookie.getValue
var values = "MYSAPSSO2=" + MYSAP(0) + "; JSESSIONID=" + MYJS(0)
def test : Option[(String, Array[String])] = {
Some("cookie" → Array(values))
}
之后我将测试函数转储到控制台并显示此结果(id不同,因为它是一个新部署的应用程序:
MYSAPSSO2=AjExMDAgABBwb3J0YWw6ZV9nYW1zbTAxiAAHZGVmYXVsdAEACUVfR0FNU00wMQIAAzAwMAMAA1NQRAQADDIwMTMxMTMwMjEyMAUABAAAAAgKAAlFX0dBTVNNMDH%2FAQYwggECBgkqhkiG9w0BBwKggfQwgfECAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHATGB0TCBzgIBATAkMBsxCzAJBgNVBAYTAk5MMQwwCgYDVQQDEwNTUEQCBQCEogh2MAkGBSsOAwIaBQCgXTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0xMzExMzAyMTIwMzdaMCMGCSqGSIb3DQEJBDEWBBSryP8YWrWBPrzQBMyIypyfgGJT2TAJBgcqhkjOOAQDBC4wLAIUaMRLpG%2FxZYhzRIbyXzibMJJIGNcCFF4mmIESPh9o7kd7k46NNkr9ESLg;
JSESSIONID=TCaFUY3kaqppP-IakFa0KDRgeOKqQgGScngA_SAP158n6gVEgGH7sItNCAOyfIFO
所以问题就出现了为什么示例3中的代码在2中没有的情况下工作。 我希望Orbeon可以帮助我跟踪这个问题的根源并植入更多Netweaver友好的cookie转发方式,如例1所示。