警告巨大投稿!
今年の初めに、次の質問を投稿しました: 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 は Tomcat とは少し異なるセッション ID を処理するということです。sessionid と JSESSIONID が同じではありません。以前の投稿で既に示したように、セッション ID は 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 では同じではありません (セッションで述べたように、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 が必要です。
このコードを追加したことを確認するには: Code from 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
本当に私が望んでいたものではありません。では、これはどのようにして可能になるのでしょうか? こことその間で空想的なことは何も起こっていません。正しい値を示した印刷ステートメントが sessionCookieFromIncoming にあったため、値が sessionCookieFromGuess メソッドから来ていないことはわかっています。
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 が、この問題の根本を追跡し、例 1 に示すような、より Netweaver に適した Cookie 転送方法を埋め込むのに役立つことを願っています。