対象: root/programs/CS/Samples4NetCore/Backend(net10.0) / 最終更新: 2026-10-16
上位: Samples4NetCore/ANALYSIS.md(区画の俯瞰・前提・ビルド・net48 との対応)
.NET 10 の ASP.NET Core で Open棟梁 を使う、現行の推奨サンプル(2 本)。
どちらも Microsoft.NET.Sdk.Web、Host.CreateDefaultBuilder + Startup 方式(Minimal API ではない)。
| サンプル | 種類 | 親クラス 2 | 認証 |
|---|---|---|---|
MVC_Sample |
ASP.NET Core MVC(画面あり) | MyBaseMVControllerCore |
Cookie 認証(フォーム ログイン、OAuth2 の認可コード グラント) |
ASPNETWebService |
Web API(ResourceServer。画面なし) | MyBaseAsyncApiController 属性 |
Authorization: Bearer(無くても通す) |
コンテナで動かす一式は、リポジトリ直下の container/README.md。
// Program.cs
OAuth2AndOIDCClient.HttpClient = new HttpClient(); // 静的な HttpClient を差し込む
// Startup.cs(コンストラクタ)
GetConfigParameter.InitConfiguration(configuration); // ★必須。無いと設定がすべて読めない
// Startup.Configure
app._UseHttpContextAccessor(); // ★必須。MyHttpContext.Current を使えるようにする
app.UseSession(...); // セッションを使うなら(MVC_Sample のみ)InitConfiguration/_UseHttpContextAccessor/UseSessionの 3 点が定型_UseHttpContextAccessorはFramework.StdMigration.HttpContextExtensionsの拡張メソッド。System.Web.HttpContext.Currentに当たるものをMyHttpContext.Currentとして用意する (Framework/ANALYSIS.md4.2 節)Host.CreateDefaultBuilderが環境変数を構成に含め、そのIConfigurationをInitConfigurationに渡すので、 環境変数(appSettings__キー)の上書きがフレームワークの読む値にも効く(4 節)
| コントローラ | 内容 |
|---|---|
HomeController |
Login(フォーム ログイン。ユーザ名が空でなければ認証する)、OAuth2AuthorizationCodeGrantClient(認可コード → トークン → id_token の検証 → UserInfo → SignInAsync)、Saml2AssertionConsumerService(SAML2 の応答の検証 → SignInAsync)、Logout、Scroll |
Crud1Controller / Crud2Controller |
CRUD。2 つは実質同じ(どちらも Html.BeginForm。違いは遷移先だけ) |
ErrorController / PingController |
エラー画面・死活確認 |
Crud1/Crud2/Home/Errorに[Authorize(AuthenticationSchemes = Cookie)]。ログインまわりは[AllowAnonymous]- B 層は
await layerB.DoBusinessLogicAsync(...)で呼ぶ(net48 版は同期のDoBusinessLogic)。 ただし中身は別スレッドで同期版を走らせているだけである(Frameworks/ANALYSIS.md4.4 節) - B 層・D 層は
Logic/{Business, Common, Dao}(LayerB/LayerD/ 自動生成 DaoDaoShippers) wwwroot/lib/(bootstrap など)はリポジトリに直接置いている。npm / grunt は使わないlaunchSettings.jsonのプロファイルはhttps(44334) だけ(Kestrel)。外部ログインの戻り先の登録(44334)と合わせるため。 net48 版の MVC_Sample(IIS Express)も 44334 なので、同時には動かせない
OAuth2 の流れを動かすには、別リポジトリの汎用認証サイト(MultiPurposeAuthSite)のスタブが要る(#649)。
接続先は appsettings.json の SpRp_* / OAuth2AndOidc* / JwkSetUri(既定は MPAS のスタブ https://localhost:44310。
起動は Sample4SpRp/README.md 2 節)。
クライアントは MPAS の雛形の MVC_Sample で、戻り先は https://localhost:44334/Home/OAuth2AuthorizationCodeGrantClient
(この URL で動かさないと、戻り先が登録と合わない)。id_token の鍵は SpRp_DiscoveryUri の jwks_uri から引く。
単体ではフォーム ログインまでしか動かない。**外部ログインは 2・3 に載っていないので、手で確かめる。**キーの意味(相手の値か自分の値か)は
Framework/ANALYSIS.md 8.1 節。
SAML2 の外部ログインも同じスタブを使う(SpRp_Saml2*・SpRp_RsaPfx*)。
- 要求も応答も HTTP-Redirect。 NameID は Persistent を求め、識別子は NameID、表示名は属性の
mail(OIDC のsub/emailと同じ分け方) - IdP の SSO の口と署名鍵は、メタデータ(
SpRp_Saml2MetadataUri)から引く(entityID はSpRp_Saml2EntityIdと照合する) - AuthnRequest の Issuer は
http://+ client_id(汎用認証サイトは、Issuer から client_id を引く)。要求にはSpRp_RsaPfxFilePathの鍵で署名する - ACS は
https://localhost:44334/Home/Saml2AssertionConsumerService。MPAS の雛形のMVC_Sampleにredirect_uri_samlとして登録が要る (無いと IdP は応答を返さない)
| コントローラ | ルート | 内容 |
|---|---|---|
JsonController |
api/Json/<action> |
Legacy の WSServer_sample の B 層を、CRUD の個別 Web メソッドとして公開する |
BatchUpdateController |
api/BatchUpdate/<action> |
DTO(DTTables)の往復とバッチ更新。RowState / Original を保ち、楽観排他する |
SampleDataController / ValuesController |
api/<controller>/<action> |
動作確認用 |
Legacy/WS_sample/Build/net10.0/のWSServer_sample.dll/WSIFType_sample.dllをHintPathで参照する。6_Build_WSSrvCore_sample.batが先にWSServer_sampleを建ててそこへ複写し、続けて本プロジェクトを建てる- 自前の
Logic/(SuppliersLayerB/DaoSuppliers)も持つ Bearer(アクセス トークン)の発行者は MPAS のスタブ(appsettings.jsonのSpRp_Isser=https://localhost:44310、 鍵はJwkSetUri=/jwkcerts。#649)。検証はAccessToken.Verifyの既存の版(鍵と iss は設定から。aud は確かめない。#601)GET api/json/claimsは、Bearer の検証の結果を返す({ userName, roles, scopes }。#649)。 SPA のサンプル(Sample4SpRp/SPA)が使う。 トークンが無い・検証に失敗したときも 200 で、userNameは「未認証」。DB は読まない- OpenAPI を標準機能で出す(
AddOpenApi/MapOpenApi、/openapi/v1.json。#580)。Microsoft.OpenApiは脆弱性のある推移的な版を避けるため csproj に明示している MVC_Sampleと違い、Cookie 認証・セッション・データ保護を持たない(AddMvcも不要。#582)。 一方、CORS を持つのはこちらだけappsettings.jsonの定義ファイルのパスはC:/root/files/resource/XML/...(XMLが大文字)。 Windows では通るが、Linux では開けない(CONFIGURATION.md7-1。コンテナでは別の設定で上書きしている)
appsettings.json の値は、環境変数でそのまま上書きできる。 区切りは __(下線 2 つ)。
appSettings__FxXMLSPDefinition=/app/files/resource/Xml/SPDefinition.xml
connectionStrings__ConnectionString_SQL=Data Source=db;...
FxContainerizationは要らない。 あちらは ON のとき「接頭辞なしのキー名」で環境変数を読む別の仕組みである (CONFIGURATION.md4 節)。
両サンプルとも、環境ごとに変えたい振る舞いを appSettings のキーで切り替える口を持つ
(Startup.cs 冒頭のコメントに一覧がある)。既定はいずれも従来どおり(サンプルは平文 HTTP で動かすため)。
| キー | 既定 | 効果 | ASPNETWebService |
|---|---|---|---|
UseHttpsRedirection |
off |
on で app.UseHttpsRedirection() を挟む |
あり |
CookieSecurePolicy |
(空) | always で Cookie に Secure を必ず付ける |
—(Cookie を使わない) |
DataProtectionKeyPath |
(空) | データ保護の鍵を、指定フォルダへ永続化する | — |
UseForwardedHeaders |
off |
X-Forwarded-Proto / -For を取り込む(#549) |
あり |
ForwardedHeadersKnownProxies |
(空) | 信用する前段のアドレス(空 = 範囲を制限しない) | あり |
① UseHttpsRedirection は、on にしただけでは何もしない。
リダイレクト先のポートが決まらないと、警告を 1 行出して素通りする。有効にしたのに HTTP のまま 200 が返る。
warn: Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware[3]
Failed to determine the https port for redirect.
| 与え方 | 結果(実測) |
|---|---|
ASPNETCORE_HTTPS_PORT=44399(単数) |
307 Location: https://localhost:44399/... |
HTTPS_PORT=44399 |
307(同上) |
ASPNETCORE_HTTPS_PORTS=44399(複数) |
効かない(200 のまま) |
複数形は Kestrel が待ち受けるポートを決めるもので、このミドルウェアが読むのは単数形。
② CookieSecurePolicy=always を平文 HTTP でやると、ログインできなくなる。
Antiforgery の Cookie も返らなくなるため、症状は**「ログイン画面は出るが、POST が 400」**になる。
③ データ保護は AddCookie ではなくアプリ全体に設定する。
AddCookie の options.DataProtectionProvider は認証 Cookie にしか効かない。
セッションと Antiforgery も同じ鍵を使うので、services.AddDataProtection() 側に置く。
services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(keyPath))
.SetApplicationName("MVC_Sample"); // 既定はコンテンツ ルートのパス由来SetApplicationName も要る。 既定のアプリケーション名はコンテンツ ルートのパスから決まるため、
鍵を共有していても配置先のパスが違うと復号できない(Windows の C:\... とコンテナの /app など)。
net48 側の対応物は machineKey(Samples/WebApp_sample/MVC_Sample の Web.config のコメント)。
④ リバース プロキシで TLS を終端するなら UseForwardedHeaders が要る(#549)。
前段で終端すると、アプリから見た接続は HTTP になる。Request.IsHttps が false のままなので、
ブラウザは HTTPS で繋いでいるのに Secure 属性が付かない(#536 でフレームワークが立てるようにした分が効かない)。
実測(X-Forwarded-Proto: https を付けて、平文 HTTP でログインしたときの Set-Cookie)。
| 設定 | secure が付いた Cookie |
|---|---|
既定(off) |
0 / 1 件 |
UseForwardedHeaders=on |
3 / 4 件(SessionTimeOut / .AspNetCore.Cookies / mvc_session) |
on + ForwardedHeadersKnownProxies=10.0.0.1 |
0 / 1 件(前段の範囲外なので捨てられる) |
on + ヘッダ無し |
0 / 1 件(素の HTTP のまま。正しい) |
KnownIPNetworks/KnownProxiesを設定しないと黙って無視される。 既定ではループバックからの転送しか信用しない。コンテナや Kubernetes では前段が別アドレスになるため、 指定しないと何も起きない。「on にしたのに直らない」の原因はほぼこれ。逆に無条件に信用すると、クライアントがヘッダを詐称できる。前段だけが到達できるネットワークに閉じてから使うこと。
net48 側はコードから変えられない(Request.IsSecureConnection は読み取り専用)ため、
IIS + ARR の URL Rewrite で HTTPS サーバ変数を立てる(CONFIGURATION.md 8 節)。
| bat | 建てるもの |
|---|---|
6_Build_WSSrvCore_sample.bat |
Legacy/WS_sample/WSServer_sample → Build/net10.0/ へ複写 → ASPNETWebService |
10_Build_WebAppCore_sample.bat |
MVC_Sample |
| 疎通テスト | ホスト | 確かめること |
|---|---|---|
MVC_Sample (net10.0) |
Kestrel(51083) | /Home/Login を GET → 偽造防止トークンを付けて POST → /Crud1/Index が 200 |
TestWebAPIClient (net10.0) |
Kestrel(51088) | ASPNETWebService に対して CRUD の一巡・DTO の往復・楽観排他 |
OpenAPI (net10.0) |
Kestrel(51093) | /openapi/v1.json が仕様として読める(版・paths・代表的な API が名前で載っている) |
どれも DB(Northwind)が要る(OpenAPI を除く)。詳細は SMOKETEST.md。
InitConfiguration/_UseHttpContextAccessorを忘れると、設定やMyHttpContext.Currentが読めない(2 節)。ASPNETWebServiceは Legacy のWSServer_sampleに依存する(3.2 節)。6_の bat を経由せずに建てると古い DLL を見る。Crud1とCrud2は同じもの(3.1 節)。片方だけ直すと食い違う。ASPNETWebServiceのXMLは大文字(3.2 節)。Linux では読めない。- 4 節の切り替えは、組み合わせを誤ると「設定したのに何も起きない」になる(4.1 節)。
- OAuth2 の流れは外部の認証サイトが要る(3.1 節)。疎通テストはフォーム ログインだけを見る。
- 部品を先にビルドする(
Nuget_netcore100.sln→Business_netcore100.sln) -
ASPNETWebServiceを触るなら、6_Build_WSSrvCore_sample.batで建てる - 設定のキーを足したら、
appsettings.jsonと、コンテナ用のcontainer/*/appsettings.Container.json/docker-compose.ymlを見る - 変えたサンプルだけを
-Onlyで疎通する - net48 版(
Samples/WebApp_sample/MVC_Sample、Samples/WS_sample/ASPNETWebService)への追随の要否を報告する