0

警告巨大的帖子!

今年年初我发布了这个问题: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 中它们是相同的。

1.

让我们看一下方法 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 上是不一样的(就像我在 session 中所说的是 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)

2.

返回到 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 方法,因为显示正确值的打印语句位于 sessionCookieFromIncoming 中。

3.

所以我开始研究并想出了这个(同样不是 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 forwardig 方式,如示例 1 所示。

4

0 回答 0