From 4f1ef6b672e420d7aa40a483d5e36438ae19fd34 Mon Sep 17 00:00:00 2001 From: nishi_74322014 Date: Sat, 15 Aug 2026 13:33:46 +0900 Subject: [PATCH 1/5] fixing #541 --- .../MVC_Sample/MVC_Sample/Web.config | 27 +++ root/programs/CS/Samples4NetCore/ANALYSIS.md | 72 ++++++++ .../Backend/MVC_Sample/MVC_Sample/Startup.cs | 169 ++++++++++++++++-- .../MVC_Sample/MVC_Sample/appsettings.json | 37 ++++ 4 files changed, 291 insertions(+), 14 deletions(-) diff --git a/root/programs/CS/Samples/WebApp_sample/MVC_Sample/MVC_Sample/Web.config b/root/programs/CS/Samples/WebApp_sample/MVC_Sample/MVC_Sample/Web.config index fbeaf2b1a..54fa77ef1 100644 --- a/root/programs/CS/Samples/WebApp_sample/MVC_Sample/MVC_Sample/Web.config +++ b/root/programs/CS/Samples/WebApp_sample/MVC_Sample/MVC_Sample/Web.config @@ -10,6 +10,14 @@
+ @@ -64,6 +72,25 @@ of SQL Server (including SQL Azure and SQL Compact) instead of to SQL Server Express. --> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/root/programs/CS/Samples4NetCore/Docker/docker-compose.yml b/root/programs/CS/Samples4NetCore/Docker/docker-compose.yml new file mode 100644 index 000000000..bab5bdea6 --- /dev/null +++ b/root/programs/CS/Samples4NetCore/Docker/docker-compose.yml @@ -0,0 +1,76 @@ +# MVC_Sample (net10.0) を Docker で動かす(#548) +# +# 前提:DB は LocalServicesOnDocker が提供する。先に起動しておくこと。 +# https://github.com/NetDevInfraWGinOSSConsortium/LocalServicesOnDocker +# あちらが作る common_link に相乗りし、サービス名 sqlserver で届く。 +# +# <値をどこに書くか> +# ・配置に依らない「コンテナならこう」 → appsettings.Container.json +# ・配置ごとに変わる値・秘密 → ここ(environment) +# 読み込み順は appsettings.json → appsettings.Container.json → 環境変数で、 +# **後が勝つ**ので、ここに書けば JSON より優先される。 + +services: + mvc-sample: + image: opentouryo-mvc-sample + build: + context: . + dockerfile: Dockerfile + ports: + - "8080:8080" + - "8081:8081" + environment: + # Container 環境として起動する(appsettings.Container.json が読まれる)。 + # **Development にはしない。** 開発者例外ページが出てしまうため。 + - ASPNETCORE_ENVIRONMENT=Container + + # 待ち受けポート + - ASPNETCORE_HTTP_PORTS=8080 + - ASPNETCORE_HTTPS_PORTS=8081 + + # 証明書(PEM + 秘密鍵。**パスワードを持たない**) + - Kestrel__Certificates__Default__Path=/https/aspnetapp.pem + - Kestrel__Certificates__Default__KeyPath=/https/aspnetapp.key + + # リソースの置き場所 + # + # Open棟梁は設定値の中の %変数% を自前で展開する + # (ResourceLoader.ResolveFilePath → StringVariableOperator)。 + # Windows の書式に依存しない実装なので、Linux コンテナでも効く。 + - OT_RESOURCE_ROOT=/app/files/resource + # ログの出力先(**リソースは ro でマウントするので、ログは別の場所へ**) + - OT_LOG_ROOT=/app/logs + + # 接続文字列 + # + # **Data Source は localhost ではなく sqlserver。** + # コンテナから見た localhost は自分自身であり、DB には届かない。 + # パスワードを直に書いているのは、すぐ動かせるサンプルだからである。 + # 実際の環境では secrets やシークレット ストアから渡すこと(README 参照)。 + - connectionStrings__ConnectionString_SQL=Data Source=sqlserver;Initial Catalog=Northwind;User ID=sa;Password=seigi@123;Encrypt=false; + + volumes: + # 定義ファイル・SQL・証明書(読み取り専用) + - ../../../../files/resource:/app/files/resource:ro + # HTTPS の開発用証明書(0_SetupCert.ps1 が作る。読み取り専用) + - ./https:/https:ro + # ログ(書き込む) + - mvc-sample-logs:/app/logs + # データ保護の鍵 + # + # **ここを永続化しないと、コンテナを作り直すたびに鍵が変わり、 + # 認証 Cookie とセッションが失効する。** + - mvc-sample-keys:/app/keys + + networks: + - common_link + +volumes: + mvc-sample-logs: + mvc-sample-keys: + +networks: + # LocalServicesOnDocker が作るネットワークに相乗りする。 + # 先に向こうを起動しておくこと(無いと compose がエラーになる)。 + common_link: + external: true From ae38cc4e370b04867bb457e383e8cb3f6eeb69a0 Mon Sep 17 00:00:00 2001 From: nishi_74322014 Date: Sat, 15 Aug 2026 23:56:13 +0900 Subject: [PATCH 3/5] fixed #550 --- root/programs/3_SmokeTest.ps1 | 23 +++++++++++++++++-- .../ServiceInterface/WCFService/App.config | 6 ++--- root/programs/CS/Samples/ANALYSIS.md | 2 +- .../WebForms_Sample/app.config | 16 ++++++------- root/programs/CS/Samples4NetCore/ANALYSIS.md | 6 ++--- .../Backend/MVC_Sample/MVC_Sample/Startup.cs | 2 +- .../MVC_Sample/MVC_Sample/appsettings.json | 10 ++++---- .../CS/Samples4NetCore/Docker/README.md | 11 +++++---- .../Docker/appsettings.Container.json | 4 ++-- .../ASPNETWebService/app.config | 6 ++--- .../ServiceInterface/WCFService/App.config | 6 ++--- .../WebForms_Sample/app.config | 16 ++++++------- 12 files changed, 65 insertions(+), 43 deletions(-) diff --git a/root/programs/3_SmokeTest.ps1 b/root/programs/3_SmokeTest.ps1 index d3bf07e61..b152fc46b 100644 --- a/root/programs/3_SmokeTest.ps1 +++ b/root/programs/3_SmokeTest.ps1 @@ -70,6 +70,8 @@ 2026/08/01 玄人 幸道 新規作成(リリース ワークのエージェント化) 2026/08/07 玄人 幸道 Orders2が無ければ作成するようにした 2026/08/13 玄人 幸道 Lang を追加(VB 版の疎通に対応) + 2026/08/15 玄人 幸道 Args を持たない対象が PowerShell 5.1 で起動できず、 + しかも前回の出力で OK と判定されていたのを修正 #> [CmdletBinding()] param( @@ -1186,6 +1188,13 @@ foreach ($t in $selected) # Start-Process でファイルへ直接リダイレクトすれば、どちらも起きない。 # 出力は生のまま残り、環境による差も出ない。 $err = "$out.err" + + # **前回の出力を必ず消してから実行する。** + # $out / $err は対象ごとの固定名で、$OutputDir(既定は %TEMP%)に残る。 + # 消さずに実行すると、**起動に失敗しても前回の出力が判定に使われ、 + # 実行していないのに OK になる**(所要時間が 0.0 秒になるのが兆候)。 + Remove-Item $out, $err -Force -ErrorAction SilentlyContinue + Write-Host " 実行中 ..." $sw = [Diagnostics.Stopwatch]::StartNew() @@ -1199,7 +1208,7 @@ foreach ($t in $selected) $argList = @("`"$exe`"") if ($needSep) { $argList += "--" } - $argList += @($t.Args) + $argList += @($t.Args | Where-Object { $null -ne $_ }) Start-Process "dotnet" -ArgumentList $argList -NoNewWindow -Wait ` -WorkingDirectory (Split-Path $exe) ` @@ -1207,7 +1216,17 @@ foreach ($t in $selected) } else { - $argList = @($t.Args) + # **null 要素を落としてから数える。** + # Args を持たない対象では $t.Args が $null になり、@($null) は + # 「要素数 1・中身 null」の配列になる。**Count は 0 にならない**ので、 + # 下のガードをすり抜けて -ArgumentList に null 入りの配列が渡る。 + # これを Windows PowerShell 5.1 は拒否する(PS 7 は空文字に変換して通す)。 + # + # PS 5.1 : Start-Process : パラメーター 'ArgumentList の引数を確認できません。… + # PS 7 : そのまま動く + # + # 5.1 でだけ落ちるため、7 で検証していると気付けない。 + $argList = @($t.Args | Where-Object { $null -ne $_ }) if ($argList.Count -eq 0) { diff --git a/root/programs/CS/Frameworks/Infrastructure/ServiceInterface/WCFService/App.config b/root/programs/CS/Frameworks/Infrastructure/ServiceInterface/WCFService/App.config index 68720f878..70f7df870 100644 --- a/root/programs/CS/Frameworks/Infrastructure/ServiceInterface/WCFService/App.config +++ b/root/programs/CS/Frameworks/Infrastructure/ServiceInterface/WCFService/App.config @@ -4,11 +4,11 @@ - + - + - + diff --git a/root/programs/CS/Samples/ANALYSIS.md b/root/programs/CS/Samples/ANALYSIS.md index db6d3112d..6e8347dac 100644 --- a/root/programs/CS/Samples/ANALYSIS.md +++ b/root/programs/CS/Samples/ANALYSIS.md @@ -30,7 +30,7 @@ Open棟梁フレームワークの **使い方を示すサンプル兼テンプ **サンプルの設定ファイルは `C:\root\files\resource\...` という絶対パスを直書きしている。** ```xml - + ``` diff --git a/root/programs/CS/Samples/WebApp_sample/WebForms_Sample/WebForms_Sample/app.config b/root/programs/CS/Samples/WebApp_sample/WebForms_Sample/WebForms_Sample/app.config index 2f0928855..d377d2874 100644 --- a/root/programs/CS/Samples/WebApp_sample/WebForms_Sample/WebForms_Sample/app.config +++ b/root/programs/CS/Samples/WebApp_sample/WebForms_Sample/WebForms_Sample/app.config @@ -50,19 +50,19 @@ - + - + - + - + - + - - + + @@ -132,7 +132,7 @@ - + \ No newline at end of file diff --git a/root/programs/CS/Samples4NetCore/ANALYSIS.md b/root/programs/CS/Samples4NetCore/ANALYSIS.md index 52d7336d6..ab7fe2552 100644 --- a/root/programs/CS/Samples4NetCore/ANALYSIS.md +++ b/root/programs/CS/Samples4NetCore/ANALYSIS.md @@ -51,7 +51,7 @@ dotnet build ../Frameworks/Infrastructure/Business_netcore100.sln `Backend/MVC_Sample` と `Legacy/*` の設定は `C:/root/files/resource/...` を直書きしている。 ```json -"FxXMLSPDefinition": "C:/root/files/resource/XML/SPDefinition.xml", +"FxXMLSPDefinition": "C:/root/files/resource/Xml/SPDefinition.xml", "SqlTextFilePath": "C:/root/files/resource/Sql" ``` @@ -247,7 +247,7 @@ net48 の `app.config` → Core は `appsettings.json`。**`appSettings` / `conn "ConnectionString_NPS": "HOST=localhost;DATABASE=postgres;..." }, "appSettings": { - "FxXMLSPDefinition": "C:/root/files/resource/XML/SPDefinition.xml", + "FxXMLSPDefinition": "C:/root/files/resource/Xml/SPDefinition.xml", "FxLog4NetConfFile": "C:/root/files/resource/Log/SampleLogConf.xml", "FxSqlTraceLog": "on", "SqlTextFilePath": "C:/root/files/resource/Sql" @@ -268,7 +268,7 @@ net48 の `app.config` → Core は `appsettings.json`。**`appSettings` / `conn **`appsettings.json` の値は、環境変数でそのまま上書きできる。** 区切りは `__`(下線 2 つ)。 ``` -appSettings__FxXMLSPDefinition=/app/files/resource/XML/SPDefinition.xml +appSettings__FxXMLSPDefinition=/app/files/resource/Xml/SPDefinition.xml connectionStrings__ConnectionString_SQL=Data Source=db;... ``` diff --git a/root/programs/CS/Samples4NetCore/Backend/MVC_Sample/MVC_Sample/Startup.cs b/root/programs/CS/Samples4NetCore/Backend/MVC_Sample/MVC_Sample/Startup.cs index 8e128518b..4c3953fbe 100644 --- a/root/programs/CS/Samples4NetCore/Backend/MVC_Sample/MVC_Sample/Startup.cs +++ b/root/programs/CS/Samples4NetCore/Backend/MVC_Sample/MVC_Sample/Startup.cs @@ -40,7 +40,7 @@ // appsettings.json の値は環境変数で上書きできる。区切りは「__」(下線 2 つ)。 // // appSettings__UseHttpsRedirection=on -// appSettings__FxXMLSPDefinition=/app/files/resource/XML/SPDefinition.xml +// appSettings__FxXMLSPDefinition=/app/files/resource/Xml/SPDefinition.xml // connectionStrings__ConnectionString_SQL=... // // **FxContainerization は要らない。** あちらは「接頭辞なしのキー名」で diff --git a/root/programs/CS/Samples4NetCore/Backend/MVC_Sample/MVC_Sample/appsettings.json b/root/programs/CS/Samples4NetCore/Backend/MVC_Sample/MVC_Sample/appsettings.json index 55f83c319..11b086b27 100644 --- a/root/programs/CS/Samples4NetCore/Backend/MVC_Sample/MVC_Sample/appsettings.json +++ b/root/programs/CS/Samples4NetCore/Backend/MVC_Sample/MVC_Sample/appsettings.json @@ -26,7 +26,7 @@ // <環境を移すとき>(#541) // ここの値は、環境変数で上書きできる。区切りは「__」(下線 2 つ)。 // - // appSettings__FxXMLSPDefinition=/app/files/resource/XML/SPDefinition.xml + // appSettings__FxXMLSPDefinition=/app/files/resource/Xml/SPDefinition.xml // connectionStrings__ConnectionString_SQL=Data Source=db;... // // Host.CreateDefaultBuilder が環境変数を構成に含めるため、 @@ -61,13 +61,13 @@ // 基盤画面パス" "FxErrorScreenPath": "/Error/Index", // 共有情報定義へのパス - "FxXMLSPDefinition": "C:/root/files/resource/XML/SPDefinition.xml", + "FxXMLSPDefinition": "C:/root/files/resource/Xml/SPDefinition.xml", // メッセージ定義へのパス - "FxXMLMSGDefinition": "C:/root/files/resource/XML/MSGDefinition.xml", + "FxXMLMSGDefinition": "C:/root/files/resource/Xml/MSGDefinition.xml", // トランザクション制御定義へのパス - "FxXMLTCDefinition": "C:/root/files/resource/XML/TCDefinition.xml", + "FxXMLTCDefinition": "C:/root/files/resource/Xml/TCDefinition.xml", // 名前解決定義へのパス - "FxXMLTMInProcessDefinition": "C:/root/files/resource/XML/TMInProcessDefinition.xml", + "FxXMLTMInProcessDefinition": "C:/root/files/resource/Xml/TMInProcessDefinition.xml", // フレームワークの使用するパラメータ - end diff --git a/root/programs/CS/Samples4NetCore/Docker/README.md b/root/programs/CS/Samples4NetCore/Docker/README.md index 306215014..c09ae729a 100644 --- a/root/programs/CS/Samples4NetCore/Docker/README.md +++ b/root/programs/CS/Samples4NetCore/Docker/README.md @@ -99,11 +99,14 @@ OS の機能ではない。`ResourceLoader.ResolveFilePath` が `WORKDIR /app` を置かないと、**設定ファイルが一切読まれないまま起動する** (それでも画面は出るので気付きにくい)。 -### フォルダ名は `Xml`。`XML` ではない +### フォルダ名の大文字小文字は合わせる -`appsettings.json` は `C:/root/files/resource/XML/...` と書いているが、実フォルダは `Xml`。 -Windows は大文字小文字を区別しないので通るが、**Linux では開けない。** -`appsettings.Container.json` では `Xml` に直してある。 +実フォルダは `Xml`(`XML` ではない)。**Windows は大文字小文字を区別しないので +間違っていても通るが、Linux では開けない。** + +`appsettings.json` はもともと `resource/XML/...` と書いており、 +このサンプルを作る過程で見つかった。**#550 で本体側を `Xml` に直してある。** +`resource` 配下の他のフォルダ(`Log` / `Sql` / `Test` / `X509`)も同様。 ### `Data Source` は `localhost` ではなく `sqlserver` diff --git a/root/programs/CS/Samples4NetCore/Docker/appsettings.Container.json b/root/programs/CS/Samples4NetCore/Docker/appsettings.Container.json index 2a8bd232e..d7ec04f99 100644 --- a/root/programs/CS/Samples4NetCore/Docker/appsettings.Container.json +++ b/root/programs/CS/Samples4NetCore/Docker/appsettings.Container.json @@ -19,8 +19,8 @@ // フレームワークの使用するパラメータ - start // - // **フォルダ名は Xml。** appsettings.json は XML と書いているが、 - // 実フォルダは Xml であり、**大文字小文字を区別する Linux では XML では開けない。** + // **フォルダ名は Xml(XML ではない)。** + // 大文字小文字を区別する Linux では、綴りが違うと開けない(#550)。 "FxXMLSPDefinition": "%OT_RESOURCE_ROOT%/Xml/SPDefinition.xml", "FxXMLMSGDefinition": "%OT_RESOURCE_ROOT%/Xml/MSGDefinition.xml", "FxXMLTCDefinition": "%OT_RESOURCE_ROOT%/Xml/TCDefinition.xml", diff --git a/root/programs/VB/Frameworks/Infrastructure/ServiceInterface/ASPNETWebService/ASPNETWebService/app.config b/root/programs/VB/Frameworks/Infrastructure/ServiceInterface/ASPNETWebService/ASPNETWebService/app.config index 1b6c6451e..e5efdb7f5 100644 --- a/root/programs/VB/Frameworks/Infrastructure/ServiceInterface/ASPNETWebService/ASPNETWebService/app.config +++ b/root/programs/VB/Frameworks/Infrastructure/ServiceInterface/ASPNETWebService/ASPNETWebService/app.config @@ -6,11 +6,11 @@ - + - + - + diff --git a/root/programs/VB/Frameworks/Infrastructure/ServiceInterface/WCFService/App.config b/root/programs/VB/Frameworks/Infrastructure/ServiceInterface/WCFService/App.config index 9ace65d19..5ba408dee 100644 --- a/root/programs/VB/Frameworks/Infrastructure/ServiceInterface/WCFService/App.config +++ b/root/programs/VB/Frameworks/Infrastructure/ServiceInterface/WCFService/App.config @@ -4,11 +4,11 @@ - + - + - + diff --git a/root/programs/VB/Samples/WebApp_sample/WebForms_Sample/WebForms_Sample/app.config b/root/programs/VB/Samples/WebApp_sample/WebForms_Sample/WebForms_Sample/app.config index 286e190db..1dbf52f25 100644 --- a/root/programs/VB/Samples/WebApp_sample/WebForms_Sample/WebForms_Sample/app.config +++ b/root/programs/VB/Samples/WebApp_sample/WebForms_Sample/WebForms_Sample/app.config @@ -50,19 +50,19 @@ - + - + - + - + - + - - + + @@ -132,7 +132,7 @@ - + From e4d31def6c3a1ff819e70a9d12dcd08afd07c049 Mon Sep 17 00:00:00 2001 From: nishi_74322014 Date: Sun, 16 Aug 2026 01:21:11 +0900 Subject: [PATCH 4/5] fixing #549 --- AGENTS.md | 6 + .../Framework/Util/FxCmnFunction.cs | 30 ++ .../MVC_Sample/MVC_Sample/Web.config | 34 ++ root/programs/CS/Samples4NetCore/ANALYSIS.md | 29 ++ .../Backend/MVC_Sample/MVC_Sample/Startup.cs | 82 ++++- .../MVC_Sample/MVC_Sample/appsettings.json | 11 + .../CS/Samples4NetCore/Docker/README.md | 17 +- root/programs/Configuration.md | 338 ++++++++++++++++++ root/programs/SMOKETEST.md | 34 +- 9 files changed, 570 insertions(+), 11 deletions(-) create mode 100644 root/programs/Configuration.md diff --git a/AGENTS.md b/AGENTS.md index a6254b0cc..b22623b2d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -144,10 +144,16 @@ gh auth switch --user OsscJpDevInfra # 異なる場合は切り替え | 内容 | 読む文書 | |---|---| | **コーディング規約(全領域共通)** | [`CODING.md`](root/programs/CODING.md) | +| **設定ファイルの扱い(全領域共通)** | [`Configuration.md`](root/programs/Configuration.md) | | `root/programs/CS/Frameworks/` の分析 | [`Frameworks/ANALYSIS.md`](root/programs/CS/Frameworks/ANALYSIS.md) | | `root/programs/CS/Samples/` の分析 | [`Samples/ANALYSIS.md`](root/programs/CS/Samples/ANALYSIS.md) | | `root/programs/CS/Samples4NetCore/` の分析 | [`Samples4NetCore/ANALYSIS.md`](root/programs/CS/Samples4NetCore/ANALYSIS.md) | +**設定ファイルに「仕組み」を書き足したくなったら、[`Configuration.md`](root/programs/Configuration.md) +に書く。** 設定ファイルは 86 個あり、一部にだけ詳しい説明があると、 +**書かれていないファイルを「該当しない」と誤読させる。** +値の隣に書くのは「そのキーが何か」までにする(分担は同書 0 節)。 + **コードを変更する前に、[`CODING.md`](root/programs/CODING.md) と、 作業対象を所管する `ANALYSIS.md` の両方を読むこと。** diff --git a/root/programs/CS/Frameworks/Infrastructure/Framework/Util/FxCmnFunction.cs b/root/programs/CS/Frameworks/Infrastructure/Framework/Util/FxCmnFunction.cs index c309f44f5..3c7183520 100644 --- a/root/programs/CS/Frameworks/Infrastructure/Framework/Util/FxCmnFunction.cs +++ b/root/programs/CS/Frameworks/Infrastructure/Framework/Util/FxCmnFunction.cs @@ -56,6 +56,8 @@ //* 2018/03/29 西野 大介 .NET Standard対応で、削除機能に関連するメソッドを削除 //* 2018/03/29 西野 大介 .NET Standard対応で、HttpCookieのポーティング //* 2026/08/10 玄人 幸道 Cookie に Secure 属性を設定(HTTPS のときのみ。CodeQL 対応) +//* 2026/08/16 玄人 幸道 リバース プロキシで TLS を終端すると上記が効かないため、 +//* その旨と対処をコメントに追記(#549。挙動は変えていない) //********************************************************************************** using Touryo.Infrastructure.Framework.Exceptions; @@ -968,6 +970,13 @@ public static void CreateCookieForSessionTimeoutDetection() // Secure属性を設定(CodeQL: Cookie 'Secure' attribute is not set to true) // HTTPSのときだけ立てる。無条件にtrueにすると、HTTPで動かす // 開発環境やサンプルでブラウザがCookieを保存しなくなるため。 + // + // **リバース プロキシでTLSを終端すると、ここはfalseになる。**(#549) + // 利用者のブラウザはHTTPSでも、アプリから見た接続はHTTPのため。 + // アプリ側でUseForwardedHeadersを設定し、X-Forwarded-Protoを + // 取り込むこと(Samples4NetCoreのStartup.csに例がある)。 + // 確実に立てたいなら、CookiePolicyのCookieSecurePolicy.Alwaysを使う。 + // あちらは全てのSet-Cookieを後段で上書きするため、ここの判断に依存しない。 cookieOptions.Secure = MyHttpContext.Current.Request.IsHttps; // 設定 @@ -1007,6 +1016,13 @@ public static void DeleteCookieForSessionTimeoutDetection() // Secure属性を設定(CodeQL: Cookie 'Secure' attribute is not set to true) // HTTPSのときだけ立てる。無条件にtrueにすると、HTTPで動かす // 開発環境やサンプルでブラウザがCookieを保存しなくなるため。 + // + // **リバース プロキシでTLSを終端すると、ここはfalseになる。**(#549) + // 利用者のブラウザはHTTPSでも、アプリから見た接続はHTTPのため。 + // アプリ側でUseForwardedHeadersを設定し、X-Forwarded-Protoを + // 取り込むこと(Samples4NetCoreのStartup.csに例がある)。 + // 確実に立てたいなら、CookiePolicyのCookieSecurePolicy.Alwaysを使う。 + // あちらは全てのSet-Cookieを後段で上書きするため、ここの判断に依存しない。 cookieOptions.Secure = MyHttpContext.Current.Request.IsHttps; // 設定 @@ -1046,6 +1062,13 @@ HttpCookie newCookie // Secure属性を設定(CodeQL: Cookie 'Secure' attribute is not set to true) // HTTPSのときだけ立てる。無条件にtrueにすると、HTTPで動かす // 開発環境やサンプルでブラウザがCookieを保存しなくなるため。 + // + // **リバース プロキシでTLSを終端すると、ここはfalseになる。**(#549) + // 利用者のブラウザはHTTPSでも、IISから見た接続はHTTPのため。 + // IsSecureConnectionはコードから変えられないので、IIS側で + // X-Forwarded-Protoを見てHTTPSサーバ変数を立てる + // (Samples/WebApp_sample/MVC_SampleのWeb.configに例がある)。 + // 確実に立てたいなら、forms要素のrequireSSL="true"を使う。 newCookie.Secure = HttpContext.Current.Request.IsSecureConnection; // セッションタイムアウト検出用Cookie(データ有) @@ -1085,6 +1108,13 @@ HttpCookie newCookie // Secure属性を設定(CodeQL: Cookie 'Secure' attribute is not set to true) // HTTPSのときだけ立てる。無条件にtrueにすると、HTTPで動かす // 開発環境やサンプルでブラウザがCookieを保存しなくなるため。 + // + // **リバース プロキシでTLSを終端すると、ここはfalseになる。**(#549) + // 利用者のブラウザはHTTPSでも、IISから見た接続はHTTPのため。 + // IsSecureConnectionはコードから変えられないので、IIS側で + // X-Forwarded-Protoを見てHTTPSサーバ変数を立てる + // (Samples/WebApp_sample/MVC_SampleのWeb.configに例がある)。 + // 確実に立てたいなら、forms要素のrequireSSL="true"を使う。 newCookie.Secure = HttpContext.Current.Request.IsSecureConnection; // セッションタイムアウト検出用Cookie(データ空) diff --git a/root/programs/CS/Samples/WebApp_sample/MVC_Sample/MVC_Sample/Web.config b/root/programs/CS/Samples/WebApp_sample/MVC_Sample/MVC_Sample/Web.config index 54fa77ef1..d4b72f7e2 100644 --- a/root/programs/CS/Samples/WebApp_sample/MVC_Sample/MVC_Sample/Web.config +++ b/root/programs/CS/Samples/WebApp_sample/MVC_Sample/MVC_Sample/Web.config @@ -91,6 +91,40 @@ (Samples4NetCore の appsettings.json : DataProtectionKeyPath)。 --> + + +``` + +```xml + + +``` + +--- + +## 6. コンテンツ ルート(=プロセスの作業ディレクトリ) + +**`appsettings*.json` は、実行ファイルの場所ではなく「作業ディレクトリ」から読まれる。** + +作業ディレクトリが違うと、**設定ファイルが一度も読まれないまま起動する。** +それでも画面は出るので気付きにくい。起動ログで確かめられる。 + +``` +info: Microsoft.Hosting.Lifetime[0] + Content root path: C:\OpenTouryo\root\programs ← 意図した場所か? +``` + +- コンテナでは `Dockerfile` に **`WORKDIR /app`** を置く +- `dotnet <パス>\App.dll` で起動するときは、**出力フォルダを作業ディレクトリにする** + +--- + +## 7. パスの落とし穴 + +### 7-1. 大文字小文字(#550) + +**実フォルダは `Xml` / `Log` / `Sql` / `Test` / `X509`。** +`XML` や `test` と書いても **Windows では通り、Linux では開けない。** + +### 7-2. 絶対パス + +サンプルは `C:/root/files/resource/...` を直書きしている(リポジトリを `C:\root\` に +展開する前提)。**別の場所に置くならビルドは通るが実行時に落ちる。** +環境変数(4 節)か `%変数%`(5 節)で差し替える。 + +### 7-3. 相対パスの基準 + +相対パスは**まず作業ディレクトリ基準**で探し、見つからなければ +**`AppContext.BaseDirectory`(実行ファイルの場所)基準**で再探索する +(`ResolveFilePath`)。CLI が任意の場所から起動される場合への対応。 + +`Samples4NetCore/Legacy/*` は、この仕組みに乗って**ファイル名だけ**を書いている。 + +```json +"FxXMLSPDefinition": "SPDefinition.xml" +``` + +csproj の `CopyToOutputDirectory` で出力フォルダへ配る前提なので、 +**`%変数%` 化すると壊れる。** + +--- + +## 8. HTTPS 関連 — 「検知」と「宣言」 + +リバース プロキシで TLS を終端すると、**アプリから見た接続は HTTP になる**。 +`Request.IsHttps`(net48 は `IsSecureConnection`)は false のままで、 +**ブラウザは HTTPS なのに Cookie に `Secure` が付かない**(#549)。 + +対処は 2 通りある。 + +| 方針 | 手段(net10.0) | 手段(net48) | 実測 | +|---|---|---|---| +| **検知**(実態を知らせる) | `UseForwardedHeaders` | IIS の URL Rewrite で `HTTPS` を立てる | 4 件中 **3 件**に `secure` | +| **宣言**(そう決め打つ) | `CookieSecurePolicy=always` | `forms` の `requireSSL="true"` | 4 件中 **4 件** | + +**宣言の方が依存が少なく確実。** `CookiePolicy` はすべての `Set-Cookie` を後段で +上書きするため、個々の箇所が何を判断しているかに依存しない。 + +### 検知を選ぶなら 3 点が要る + +| | 内容 | 欠けると | +|---|---|---| +| ① 前段が伝播する | `X-Forwarded-Proto: https` を付ける | 何も起きない | +| ② **アプリが受け取る設定になっている** | `UseForwardedHeaders` | **付いていても捨てられる** | +| ③ 付けられるのが前段だけ | ネットワークで閉じる/`KnownProxies` | クライアントが詐称できる | + +> **`KnownIPNetworks` / `KnownProxies` を設定しないと黙って無視される。** +> 既定ではループバックからの転送しか信用しない。 +> 「on にしたのに直らない」の原因はほぼこれ。 + +### 何を矯正でき、何ができないか + +**分かれ目は「リクエストごとに変わるか」。** + +| 情報 | 性質 | 内部パラメタで矯正できるか | +|---|---|---| +| スキーム(HTTPS か) | 環境ごとに固定 | **できる**(`CookieSecurePolicy` / `requireSSL`) | +| 配置パス(サブパス) | 環境ごとに固定 | **できる**(`app.UsePathBase`) | +| 外部から見た URL | 環境ごとに固定 | **できる**(設定に絶対 URL を書く) | +| **クライアント IP** | リクエストごとに変わる | **できない**(伝播が必須) | +| **クライアント証明書** | リクエストごとに変わる | **できない**(伝播が必須) | + +**クライアント IP は既に動く。** `GetClientIpAddress` と `MyBaseAsyncApiController` が +`X-Forwarded-For` を**ヘッダから直読み**しており、`UseForwardedHeaders` に依存しない。 + +### 宣言のトレードオフ + +**間違えるとはっきり壊れる。** 本当に平文 HTTP の環境で `always` にすると、 +Antiforgery の Cookie が返らず**ログインの POST が 400** になる(実測)。 + +**ただしこれは利点でもある。** + +| | 間違えたときの現れ方 | +|---|---| +| 検知 | **静かに効かない。** 画面は動き、`Secure` だけが付かない | +| 宣言 | **はっきり壊れる。** すぐ気付いて直せる | + +--- + +## 9. 秘密の扱い + +サンプルは**パスワードを直書きしている**(すぐ動かせることを優先しているため)。 +実際の環境では、次のいずれかで渡す。 + +| | net48 | net10.0 | +|---|---|---| +| 別ファイルへ逃がす | `` | `appsettings.{環境名}.json` | +| 暗号化する | `aspnet_regiis -pef connectionStrings <パス>` | — | +| 環境変数 | — | `connectionStrings__ConnectionString_SQL=...` | +| 開発機のみ | — | `dotnet user-secrets`(Development のみ読まれる) | +| コンテナ | — | secrets + `AddKeyPerFile`(4-1 節) | +| そもそも持たない | `Integrated Security=SSPI` | 同左 | + +**証明書は「パスワードを無くす」選択肢がある。** PFX + パスワードではなく +PEM + 秘密鍵ファイルにすると、管理対象が 1 つ減る。 + +``` +dotnet dev-certs https --format Pem -ep ./https/aspnetapp.pem -np +``` + +--- + +## 10. net48 / net10.0 の対応表 + +| | net48 | net10.0 | +|---|---|---| +| ファイル | `app.config` / `Web.config` | `appsettings.json` | +| 環境別 | (なし。`configSource` で分ける) | `appsettings.{環境名}.json` | +| 初期化 | 暗黙 | **`InitConfiguration()` が必須** | +| 環境変数での上書き | (標準では無い) | `__` 区切り | +| Cookie の `Secure` を必ず立てる | `requireSSL="true"` | `CookieSecurePolicy=always` | +| 転送ヘッダの取り込み | IIS の URL Rewrite | `UseForwardedHeaders` | +| 鍵の共有(複数台) | `machineKey` | DataProtection(`DataProtectionKeyPath`) | +| セッションの外出し | `sessionState mode="StateServer"` ほか | `AddDistributedSqlServerCache` ほか | + +--- + +## 11. 実例はどこにあるか + +| 見たいもの | 場所 | +|---|---| +| net10.0 の Web(本番向けの切り替えを含む) | `CS/Samples4NetCore/Backend/MVC_Sample/MVC_Sample/appsettings.json` | +| 環境変数・`%変数%`・環境別ファイルの実運用 | `CS/Samples4NetCore/Docker/`([`README.md`](CS/Samples4NetCore/Docker/README.md)) | +| net48 の Web(`machineKey` / 転送ヘッダの注記) | `CS/Samples/WebApp_sample/MVC_Sample/MVC_Sample/Web.config` | +| 相対パスで自己完結させる書き方 | `CS/Samples4NetCore/Legacy/Bat_sample/*/appsettings.json` | +| 領域ごとの事情 | 各 `ANALYSIS.md`([Frameworks](CS/Frameworks/ANALYSIS.md) / [Samples](CS/Samples/ANALYSIS.md) / [Samples4NetCore](CS/Samples4NetCore/ANALYSIS.md)) | diff --git a/root/programs/SMOKETEST.md b/root/programs/SMOKETEST.md index ee4fc43da..e7793be61 100644 --- a/root/programs/SMOKETEST.md +++ b/root/programs/SMOKETEST.md @@ -48,6 +48,37 @@ cd root\programs **実行順は `1_BuildAll.ps1` → `2_RunAllTests.ps1` → `3_SmokeTest.ps1`。** リリース時の作業全体は [`RELEASE.md`](RELEASE.md) を参照。 +### 判定は「今回の出力」だけで行う(#550 で一般化) + +**前回の出力が残っていると、起動に失敗しても合格になる。** +疎通テストは期待結果ファイルを持たず、**実行して出てきたもの**を判定条件と突き合わせる。 +出力が今回のものである保証が無ければ、判定そのものが成り立たない。 + +そこで `3_SmokeTest.ps1` は、**対象を実行する前に前回の残骸を必ず消す。** + +| 消すもの | 何のためか | +|---|---| +| `$OutputDir\<対象名>.txt` / `.err`(標準出力・標準エラー) | 起動に失敗しても前回の出力で判定してしまうのを防ぐ | +| `$OutputDir\daogen_*`(生成物) | 「生成された」の判定が甘くなるのを防ぐ(6 節) | + +**対象を足すときは、出力先を対象ごとに分け、実行前に消すこと。** + +> **見分け方 : 所要時間が `0.0 秒` の対象は疑う。** +> 実際に起動していれば、どれだけ速くても 0.0 秒にはならない。 +> +> ``` +> === TestTransmission (net48) === +> 実行中 ... +> Start-Process : パラメーター 'ArgumentList の引数を確認できません。… +> 出力 : NG : 0 件 +> OK (0.0 秒) ← 起動に失敗しているのに OK +> ``` +> +> これは実際に起きた(`#550` の検証中)。`Args` を持たない対象で +> `-ArgumentList` に null 入りの配列が渡り、**Windows PowerShell 5.1 でだけ** +> 起動に失敗していた(PS 7 は null を空文字に変換して通すため気付けない)。 +> 残骸を消していなかったため、前回の出力で合格していた。 + --- ## 3. 対象(23 件) @@ -123,7 +154,8 @@ net48 版は `System.CommandLine` / `Sharprompt` の .NET Framework サポート 全テーブルを回しても時間がかかるだけで、疎通としては同じことを見ているため。 生成先は `%TEMP%\OpenTouryoSmokeTest\daogen_*`。 -実行前に前回の生成物を消す。残っていると「生成された」の判定が甘くなる。 +実行前に前回の生成物を消す。残っていると「生成された」の判定が甘くなる +(全対象に共通の原則。2 節「判定は『今回の出力』だけで行う」)。 > **GUI 側の確認は手作業に残る。** 引数なしで起動すると `Application.Run(new Form1())` になる。 From 12cea4a3eda2aeaf78f747186713e20c4463d465 Mon Sep 17 00:00:00 2001 From: nishi_74322014 Date: Sun, 16 Aug 2026 01:45:11 +0900 Subject: [PATCH 5/5] fixed #541 --- .../{Configuration.md => CONFIGURATION.md} | 2 +- .../MVC_Sample/MVC_Sample/Web.config | 39 ++++++---------- .../MVC_Sample/MVC_Sample/appsettings.json | 45 +++++-------------- .../Docker/appsettings.Container.json | 25 +++-------- 4 files changed, 33 insertions(+), 78 deletions(-) rename root/programs/{Configuration.md => CONFIGURATION.md} (99%) diff --git a/root/programs/Configuration.md b/root/programs/CONFIGURATION.md similarity index 99% rename from root/programs/Configuration.md rename to root/programs/CONFIGURATION.md index afb93fbb0..8a260b033 100644 --- a/root/programs/Configuration.md +++ b/root/programs/CONFIGURATION.md @@ -1,4 +1,4 @@ -# Configuration.md — 設定ファイルの扱い +# CONFIGURATION.md — 設定ファイルの扱い 対象: `root/programs` 配下(CS / VB、net48 / net10.0) 配置: `root/programs` diff --git a/root/programs/CS/Samples/WebApp_sample/MVC_Sample/MVC_Sample/Web.config b/root/programs/CS/Samples/WebApp_sample/MVC_Sample/MVC_Sample/Web.config index d4b72f7e2..618f1e5d5 100644 --- a/root/programs/CS/Samples/WebApp_sample/MVC_Sample/MVC_Sample/Web.config +++ b/root/programs/CS/Samples/WebApp_sample/MVC_Sample/MVC_Sample/Web.config @@ -11,12 +11,8 @@ @@ -73,36 +69,30 @@ -->