-
Notifications
You must be signed in to change notification settings - Fork 0
MS_ASPNETCookieSharing
- 戻る(ASP.NET、ASP.NET Session、ASP.NET Forms認証)
- ASP.NET でSessionCookie、Cookie認証Ticketを共有する方法
- ASP.NET Core における 認証
- Cookie
-
VSソリューション プロジェクトの構成検討
にも書いたように、プロジェクト分割したいケースがある。 -
ASP.NET アプリケーションの P 層部分のプロジェクトを分割すると、
SessionCookie と、Cookie 認証 Ticket が共有できなくなり、
≒ Session が分割され、SSO もできない状態になる。 -
必要に応じて、
- SessionCookie
- Cookie 認証 Ticket
を共有する設定が必要になる。
補足(3 つの層で別々の設定が要る): 「共有できない」と一言で言っても、
実際には独立した 3 つの問題が重なっている。
どれか 1 つでも欠けると共有できない。
# 層 揃えるもの 1 ブラウザに届くか Cookie の DomainとPath(+SameSite)2 同じ Cookie を見るか Cookie の名前 3 中身を復号できるか machineKey(暗号鍵・検証鍵)4 (Session のみ)データを共有できるか Session の格納先(StateServer / SQL Server) 「設定したのに共有できない」の原因はほぼ 3 番である。
下記の処置を施せば、Session を共有可能と思われる(未検証)。
- SessionCookie を共有するサイトのドメインを指定する。
- SessionCookie 名を一致させる(既定値は
ASP.NET_SessionIdで一致している)。
- 当然、
InProcモードでは NG なので、StateServerモードを選択する。 -
machineKeyを設定する(同一マシンなら不要?)。 - アプリケーション名を設定する(設定処理は
Global.asaxなどに実装)。
<system.web>
<!-- Cookieを共有するサイトのドメインを指定 -->
<httpCookies domain=".your.site"/>
<!-- セッション StateServerにセッション保存、セッションクッキー名の指定、タイムアウト指定 -->
<sessionState
cookieless="UseCookies"
cookieName="ASP.NET_SessionId"
mode="StateServer"
regenerateExpiredSessionId="false"
stateConnectionString="tcpip=10.1.1.1:42424"
timeout="30">
</sessionState>
<!-- machineKeyを設定 -->
<machineKey
validationKey="..."
decryptionKey="..."
validation="SHA1" decryption="AES" />
</system.web>
<appSettings>
<!-- アプリケーション名を設定 -->
<add key="ApplicationName" value="appName" />
</appSettings>移行メモ: 元の掲載では
mode="StateServer"の行頭に
全角スペースが混入していたため、半角に直した。補足(「同一マシンなら不要?」への答え): 同一マシンでも必要である。
ASP.NET は既定(
machineKeyのAutoGenerate,IsolateApps)で、
アプリケーションごとに異なる鍵を自動生成する。
IsolateAppsがまさに「アプリ間で鍵を分ける」指定である。
したがって同じサーバー上の別アプリでも復号できない。さらに、
machineKeyを明示しないと、
- アプリケーション プールのリサイクル
- 再デプロイ
のたびに鍵が変わり、Session / 認証チケットが失効する
(「時々ログアウトする」の典型的な原因)。補足(
ApplicationNameが要る理由):StateServer/
SQLServerモードでは、Session の格納キーに
アプリケーション パス(/App1,/App2)が含まれる。
このため、SessionID が同じでも別アプリのデータは見えない。
Global.asaxのApplication_Startで、リフレクションにより
AppDomainのAppDomainAppId(アプリケーション名)を
強制的に同じ値に書き換える、という手法が使われてきた。
公式にサポートされた方法ではない点は理解しておく必要がある。// 参考: よく紹介される書き換え(非公式・自己責任) var appName = "/" + ConfigurationManager.AppSettings["ApplicationName"]; var runtime = typeof(HttpRuntime).GetField("_theRuntime", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null); typeof(HttpRuntime).GetField("_appDomainAppId", BindingFlags.NonPublic | BindingFlags.Instance) .SetValue(runtime, appName);
補足(Session を共有すべきかどうか): 技術的には可能だが、
アプリ間で Session を共有する設計は避けるのが望ましい。
StateServerは単一障害点であり、冗長化できない
(落ちると全アプリの Session が消える)- シリアライズ可能な型しか置けない
- どのアプリがどのキーを使うかの取り決めが暗黙になり、
結合度が上がる共有したいのが「ログイン状態」だけなら、
Session ではなく認証チケット(次節)を共有する方が筋がよい。
共有したいのが業務データなら、
DB や分散キャッシュ(Redis)に明示的に置く方が管理しやすい。
また、Forms 認証の Cookie 認証 Ticket については、
-
Cookie 認証 Ticket 名だけ一致させておけば共有できる
(既定値で一致していると思う)。 -
ドメイン
- 単一サイト内ならドメイン指定を省略出来るが、明記することも出来る。
- ドメイン間(サブ・ドメイン間)で共有するには、
EnableCrossAppRedirectsをtrueに設定する。
<authentication mode="Forms" >
<!-- The name, protection, and path attributes must match
exactly in each Web.config file. -->
<forms loginUrl="login.aspx"
name=".ASPXFORMSAUTH"
protection="All"
path="/"
domain="contoso.com"
timeout="30" />
</authentication>移行メモ(補足): 「Ticket 名だけ一致させておけば共有できる」は
不正確である。上のコメント(The name, protection, and path attributes\ must match exactly in each Web.config file.)が示す通り、
name/protection/pathの 3 つを一致させたうえで、
さらにmachineKeyを一致させる必要がある。Forms 認証チケットは
machineKeyで暗号化・署名されているため、
鍵が違えば「Cookie は届くが復号できず、未認証扱い」になる。補足(
EnableCrossAppRedirectsの役割): この設定は
「Cookie を共有する」ためのものではなく、
ReturnUrlとして別アプリケーションの URL へのリダイレクトを許可する
ためのものである(既定はfalseで、外部 URL へは飛ばさない)。つまり、
目的 設定 チケットをサブドメイン間で共有 domain=".contoso.com"(先頭のドット)チケットを復号できるようにする 同一の machineKeyログイン後に別アプリへ戻す EnableCrossAppRedirects="true"となる。上の例の
domain="contoso.com"は、
サブドメイン間で共有したいのであれば
**.contoso.com(先頭にドット)**とするのが確実である。なお
EnableCrossAppRedirects="true"は
オープン リダイレクタの入口になりうる。
遷移先 URL は必ず許可リストで検証すること。
補足(現在の環境で追加で必要になること): 上記は
SameSite属性が存在しない時代の記述である。現在は次も要る。
項目 現在の要件 requireSSL="true"HTTPS 前提。Cookie に Secureを付けるSameSite同一サイト内なら Laxで足りる。別サイトから POST で戻るならNone(+Secure必須)HttpOnlyForms 認証チケットは既定で付与される validationSHA1ではなくHMACSHA256以上にするdecryptionAES(既定のAutoでも可)上の設定例の
validation="SHA1"は
現在の基準では不十分なので、HMACSHA256に変更する。
補足: ASP.NET Core には
machineKeyが無く、
Data Protection API が同じ役割を担う
(ASP.NET Core における 認証を参照)。
アプリ間で認証 Cookie を共有するには次の 3 点を揃える。builder.Services.AddDataProtection() // ① 鍵リングを共有ストアに置く(ファイル共有 / Blob / Redis) .PersistKeysToFileSystem(new DirectoryInfo(@"\\share\keys")) // ② アプリケーション名を一致させる(machineKey の IsolateApps 相当) .SetApplicationName("SharedCookieApp"); builder.Services.ConfigureApplicationCookie(o => { // ③ Cookie 名とドメインを一致させる o.Cookie.Name = ".AspNet.SharedCookie"; o.Cookie.Domain = ".contoso.com"; o.Cookie.SameSite = SameSiteMode.Lax; o.Cookie.SecurePolicy = CookieSecurePolicy.Always; });
SetApplicationNameを揃え忘れるのが定番の失敗である
(既定でアプリごとに鍵が分離されるため、
machineKeyのIsolateAppsと同じ現象が起きる)。Session も同様に、
InProcではなく
**分散キャッシュ(Redis / SQL Server)**に置いたうえで、
Session Cookie 名を揃える。
- [ASP.NET][IIS]別アプリケーション&別サーバでセッションを共有する方法 - Qiita
https://qiita.com/mak_in/items/60f593188e770c7b7ba1- c# - Share Session between two web sites using asp.net and state server - Stack Overflow
https://stackoverflow.com/questions/3438912/share-session-between-two-web-sites-using-asp-net-and-state-server - Sharing session between two asp.net web applications
http://www.freshcodehub.com/Article/48/sharing-session-between-two-aspnet-web-applications
- c# - Share Session between two web sites using asp.net and state server - Stack Overflow
- FormsAuthentication.EnableCrossAppRedirects Property (System.Web.Security)
https://learn.microsoft.com/dotnet/api/system.web.security.formsauthentication.enablecrossappredirects - Forms Authentication Across Applications
https://learn.microsoft.com/previous-versions/aspnet/eb0zx8fc(v=vs.100) - ASP.NET Core アプリ間で Cookie を共有する
https://learn.microsoft.com/aspnet/core/security/cookie-sharing
- c# – EnableCrossAppRedirects クロスドメイン機能はどこで文書化されていますか?
https://codeday.me/jp/qa/20190405/518500.html - asp.net – クロスドメインフォーム認証クッキーの適切な作成
https://codeday.me/jp/qa/20190416/641578.html
Tags: 移行, .NET開発, ASP.NET, 認証基盤
このWikiは「Open棟梁Project」,「OSSコンソーシアム 開発基盤部会」によって運営されています。