業務イントラの認証 — Windows認証 / Forms認証 / Cookie の使い分けで業務SE が踏む選択

みなさんこんにちは!ヒロポンです!!

今回は ASP.NET 生存ガイド連載・第6回 の本論記事。業務イントラ ASP.NET で 認証どうする?? の話。

ASP.NET 案件のキックオフで「認証どうする??」と聞かれて、WinForms 時代の WindowsIdentity.GetCurrent() 感覚で答えようとして詰まったこと、ないっすか??ん? ASP.NET の認証って何種類あんねん?って手が止まる瞬間。

俺も流通系SIer 時代に同じ場面を経験しました。イントラ業務系 ASP.NET 案件で「AD 統合で SSO したい」「フォームでログイン入力する画面が欲しい」「MFA も将来入れたい」みたいな要件が並んだ時、認証方式を 3つから選ぶ判断軸が必要だと初めて気付いたんですよね。

結論から言うと、業務イントラ ASP.NET MVC 5 の認証方式は3択で、業務系の大半は Windows 認証で十分カタが付く:

  • Windows 認証 (Active Directory 統合): イントラ専用・SSO・コード変更不要
  • Forms 認証 (Cookie ベース): 外部公開・独自ユーザー管理・標準実装
  • Cookie 認証 (OWIN / ASP.NET Identity): MFA・外部プロバイダ連携・モダン拡張

連載第1〜5回(View/Controller/Routing/ORM/DI)で View 〜 Action 〜 DB アクセスの流れを押さえたので、今回は 「リクエストの認証 / 認可」 を扱います。連載通奏低音の レイヤー分離思考 が、今回は 「認証レイヤー / 認可レイヤー / セッションレイヤー」の3層分離 に再拡張されます。

この記事では VS2019 / .NET Framework 4.7.2 / C# 7.3 / ASP.NET MVC 5 環境で、3方式の最小実装と、[Authorize] 属性での認可制御、User.Identity.Name でのユーザー名取得をコード5本でまとめます。後ろの「現場メモ」で、業務系チームでルール化した時の話も書いてる。

3行で結論:

  • 業務イントラ + AD 統合ありWindows 認証一択(実装最も簡単・コード変更不要)
  • 外部公開 + 独自ユーザー管理Forms 認証 or Cookie 認証(パスワード自前管理)
  • MFA / 外部プロバイダ連携Cookie 認証(ASP.NET Identity)
目次

俺の体験 — 流通系SIer時代のイントラ認証案件

正直に書いておきます。俺が初めて ASP.NET MVC 5 で認証を扱ったのは 流通系SIer 時代 のイントラ業務システム。要件は「社内 PC から SSO で社員番号取れればいい」だけだったので、Windows 認証一択で実装完了。web.config を3行書くだけで終わって、コード変更ゼロ。

その後、別案件で社外パートナー向けの ASP.NET MVC 5 受発注画面を作った時は、Forms 認証(独自ユーザー管理)に切り替え。さらにその後、MFA 必須の経営層向け画面では Cookie 認証(OWIN + ASP.NET Identity)を導入。業務系イントラ = Windows 認証で大半カタが付く・例外で Forms / Cookie、という現場の判断軸が見えてきた経緯です。

連載通奏低音の レイヤー分離思考 が今回は 認証 / 認可 / セッションレイヤー の3層に進化します:

  • 認証レイヤー: 「あなたは誰か」を確認する(AD・パスワード・MFA)
  • 認可レイヤー: 「あなたは何ができるか」を制御する([Authorize] 属性・Role)
  • セッションレイヤー: 認証結果を保持する(Cookie・Windows トークン)

業務系の認証選びは、この 3層の関心事を分離 して考えると迷わないんですよね。

対応マップ — 3つの認証方式の比較

3方式を業務SE 視点で6観点で比較すると、こんな感じになります:

観点 Windows 認証 Forms 認証 Cookie 認証 (Identity)
用途 イントラ + AD 統合 外部公開 + 独自ユーザー モダン拡張 + MFA
ID 管理 Active Directory 自前 DB ASP.NET Identity DB
SSO ✅(ドメイン参加 PC) ❌(外部プロバイダ経由なら可)
MFA ❌(自前実装)
外部公開 ❌(VPN・モバイル不向き)
学習コスト 低(web.config + IIS のみ) 高(OWIN 設定)
パスワード管理 AD 任せ 自前ハッシュ化必須 Identity 標準実装

判断軸:

  • イントラ + AD あり → Windows 認証(実装コスト最小)
  • 外部公開 + 独自ユーザー → Forms 認証
  • MFA / 複数プロバイダ → Cookie 認証(Identity)
  • 既存 AD 環境で Cookie が要件 → Forms 認証で AD バインド

ここから順に、コード対比で見ていきます。

定石1: Windows 認証 — 最小設定でイントラ SSO

業務系イントラの最頻パターン。web.config 3行 + IIS 設定 で完結します:

<!-- ✅ 定石1: Windows 認証の web.config(最小設定) -->
<configuration>
  <system.web>
    <authentication mode="Windows" />
    <authorization>
      <deny users="?" />   <!-- 匿名ユーザーを拒否 -->
    </authorization>
  </system.web>
</configuration>

IIS 側の設定:

  1. サイトの認証で 「Windows 認証」を有効
  2. 「匿名認証」を無効
  3. アプリプールの ID がドメインユーザーで AD に問い合わせできること

これで Controller の Action 内で User.Identity.Name を呼ぶと、DOMAIN\username 形式のユーザー名が取れます:

// ✅ 定石1: Action 内でユーザー名取得
public class HomeController : Controller
{
    public ActionResult Index()
    {
        // ドメイン参加 PC からアクセスすると自動的に取れる
        string userId = User.Identity.Name;   // 例: "MYDOMAIN\\suzuki"
        bool isAuth = User.Identity.IsAuthenticated;   // true

        ViewBag.UserId = userId;
        return View();
    }
}

ポイント:

  1. コード変更ゼロweb.config と IIS 設定のみ)
  2. SSO 自動(ドメイン参加 PC からアクセスすると自動でログイン状態)
  3. User.Identity.Name で社員番号取得(AD アカウント名)
  4. 業務系イントラの大半はこれで完結

業務SE の判断軸: AD 統合できる環境ならまず Windows 認証。コード変更なしで実装が終わるので、学習コストが最も低い選択肢っす。

定石2: Forms 認証 — フォームログイン + Cookie

外部公開 or 独自ユーザー管理が要る場合の標準パターン:

<!-- ✅ 定石2: Forms 認証の web.config 設定 -->
<configuration>
  <system.web>
    <authentication mode="Forms">
      <forms loginUrl="~/Account/Login"
             timeout="60"
             slidingExpiration="true"
             requireSSL="true" />
    </authentication>
    <authorization>
      <deny users="?" />
    </authorization>
  </system.web>
</configuration>
// ✅ 定石2: Login Action での Cookie 発行
using System.Web.Security;

public class AccountController : Controller
{
    [AllowAnonymous]   // 認証前でもアクセス可
    public ActionResult Login() => View();

    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public ActionResult Login(LoginVm model, string returnUrl)
    {
        // 自前 DB でパスワード検証(ハッシュ化済み)
        var user = _userService.Authenticate(model.UserId, model.Password);
        if (user == null)
        {
            ModelState.AddModelError("", "ID またはパスワードが違います");
            return View(model);
        }

        // Cookie 発行(Forms 認証)
        FormsAuthentication.SetAuthCookie(user.UserId, model.RememberMe);

        return Redirect(returnUrl ?? "/");
    }

    public ActionResult Logout()
    {
        FormsAuthentication.SignOut();
        return RedirectToAction("Login");
    }
}

ポイント:

  1. FormsAuthentication.SetAuthCookie(userId, persistent) で Cookie 発行
  2. <forms timeout="60" slidingExpiration="true"> で60分操作なしでログアウト、操作で延長
  3. requireSSL="true" で SSL 必須化(本番運用の鉄則)
  4. パスワードハッシュ化は自前実装(PBKDF2 / Argon2 を NuGet で)

業務系で外部公開 ASP.NET MVC 5 を作る時の本命。.NET Framework 標準で追加 NuGet なしで実装できるので、学習コストが Cookie 認証より低いっす。

定石3: Cookie 認証 — OWIN + ASP.NET Identity

モダンな選択肢。MFA や外部プロバイダ連携が要る場合:

// ✅ 定石3: OWIN Startup.cs での Cookie 認証設定
using Owin;
using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Microsoft.AspNet.Identity;

[assembly: OwinStartup(typeof(MyApp.Startup))]

public partial class Startup
{
    public void ConfigureAuth(IAppBuilder app)
    {
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/Login"),
            ExpireTimeSpan = TimeSpan.FromMinutes(60),
            SlidingExpiration = true,
            CookieSecure = CookieSecureOption.Always,   // SSL 必須

            Provider = new CookieAuthenticationProvider
            {
                OnValidateIdentity = SecurityStampValidator
                    .OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                        validateInterval: TimeSpan.FromMinutes(30),
                        regenerateIdentity: (manager, user) =>
                            user.GenerateUserIdentityAsync(manager))
            }
        });

        // 外部プロバイダ追加(Microsoft, Google, etc.)
        // app.UseMicrosoftAccountAuthentication(...);
        // app.UseGoogleAuthentication(...);
    }
}

ポイント:

  1. Install-Package Microsoft.AspNet.Identity.Owin で導入
  2. UseCookieAuthentication で Cookie 認証ミドルウェア登録
  3. SecurityStampValidator でセキュリティスタンプ検証(パスワード変更時に既存セッション無効化)
  4. 外部プロバイダ連携が ASP.NET Identity の最大の旨み

学習コストは Forms 認証より高めですが、MFA / Google ログイン / Microsoft アカウント連携が要件にあるなら Cookie 認証一択。連載第5回(DI)で扱った DI コンテナとの相性も良くて、UserManager を Unity で注入する流れになります。

定石4: [Authorize] 属性で認可制御

認証通過したユーザーに対する認可(何ができるか)[Authorize] 属性で:

// ✅ 定石4: [Authorize] 属性で認可制御
public class OrderController : Controller
{
    [Authorize]   // ログイン必須(未ログインは LoginUrl にリダイレクト)
    public ActionResult Index() => View();

    [Authorize(Roles = "Admin")]   // Admin Role のユーザーのみ
    public ActionResult Delete(int id) { /* ... */ }

    [Authorize(Roles = "MYDOMAIN\\SalesGroup,MYDOMAIN\\ManagerGroup")]
    // Windows 認証で AD Group 制御(カンマ区切りで OR 条件)
    public ActionResult Export() { /* ... */ }

    [AllowAnonymous]   // 認証不要([Authorize] のオーバーライド)
    public ActionResult Public() => View();
}

// Controller 全体に適用する場合
[Authorize]
public class SecuredController : Controller
{
    [AllowAnonymous]
    public ActionResult Login() => View();   // ここだけ匿名 OK

    public ActionResult Dashboard() => View();   // ログイン必須
}

ポイント:

  1. [Authorize] で未ログイン排除(LoginUrl にリダイレクト)
  2. [Authorize(Roles = "...")] で Role 制御
  3. AD Group も Role として使える(Windows 認証時)
  4. [AllowAnonymous] でオーバーライド(Login Action 等)

業務系の認可制御は [Authorize] + Role の組み合わせで9割対応できる。データ単位の細かい認可(「自分の部署のデータだけ」等)は Action 内で User.Identity.Name を見て自前判定するパターンっす。

定石5: User.Identity.Name でユーザー情報取得

ログイン後のユーザー情報取得は3つのプロパティで:

// ✅ 定石5: User.Identity からの情報取得
public class HomeController : Controller
{
    [Authorize]
    public ActionResult Profile()
    {
        // 認証済みか
        bool isAuth = User.Identity.IsAuthenticated;

        // ユーザー名(認証方式で形式が違う)
        string userName = User.Identity.Name;
        // Windows 認証: "MYDOMAIN\\suzuki"
        // Forms 認証: "suzuki"(SetAuthCookie で渡した値)
        // Cookie 認証: "suzuki@example.com"(Identity の UserName)

        // Role 判定
        bool isAdmin = User.IsInRole("Admin");
        bool isInAdGroup = User.IsInRole("MYDOMAIN\\SalesGroup");

        // ClaimsIdentity から追加情報(Cookie 認証時)
        if (User.Identity is System.Security.Claims.ClaimsIdentity claims)
        {
            string email = claims.FindFirst(System.Security.Claims.ClaimTypes.Email)?.Value;
        }

        return View();
    }
}

ポイント:

  • User.Identity.Name で認証方式ごとに違う形式の ID 取得
  • User.IsInRole("Role名") で Role 判定(AD Group も使える)
  • ClaimsIdentity で Cookie 認証時の追加情報(メール / 電話番号 等)

業務系で「ログインユーザーの社員番号で部署を引きたい」「Admin だけメニュー表示」みたいな要件は、これらの基本 API で大半対応できる。複雑な認可は AuthorizeAttribute を継承して自前実装するパターンっす。

ハマりポイント — 実体験ベースの本番事故3点

1. Windows 認証で AD 接続できずローカル ID で動いた(半日デバッガで追ってハマった)

開発機で動いていた Windows 認証が、本番デプロイ後にローカル ID で動く事件。User.Identity.NameIIS APPPOOL\DefaultAppPool みたいな値になっていて、社員番号取得できず画面が空白になった。半日デバッガで追ってハマった末に、IIS 側の「匿名認証」が有効のままだったのが原因と判明。web.config<authentication mode="Windows"> + IIS の「匿名認証 OFF」+「Windows 認証 ON」の3点セット確認をチェックリスト化。

2. Forms 認証の Cookie 有効期限切れで突然ログアウト(30分溶かした)

業務画面の入力中に突然ログイン画面に飛ばされて入力データがロストする事件。30分溶かした末に、<forms timeout="20"> の20分タイムアウトが原因と判明。timeout="60" + slidingExpiration="true" に変更して、業務系の入力体験を改善。業務画面の Cookie 設定は60分 + slidingExpiration セットを業務系チーム規約に揃えた。

3. Cookie 認証で SSL 強制忘れで Cookie 漏洩リスク(数日プロファイラで追った)

開発環境を HTTP で動かしていた延長で本番も SSL 強制を入れ忘れる事件。数日プロファイラで追ってようやく気付いた。<httpCookies requireSSL="true"> + <forms requireSSL="true"> の SSL 強制設定 + Cookie 認証 OWIN の CookieSecure = CookieSecureOption.Always で本番では SSL 必須化。本番デプロイ前に Cookie 系の SSL 設定をチェックリスト化を業務系チーム規約に。

俺の現場メモ — 業務系チームでの認証規約

流通系SIer 時代に過去 ASP.NET MVC 5 案件を grep -rnE "authentication mode|FormsAuthentication|UseCookieAuthentication" . で50箇所近くひっかけたら、Windows 認証なのに <authentication mode="Forms"> 残骸・Forms timeout=10 で短すぎ・Cookie 認証 HTTP のままが全部入りだった。後輩と一緒に 3行ルール にまとめた:

  1. イントラ + AD あり = Windows 認証寄せ、外部公開 = Forms 認証、MFA = Cookie 認証(判断軸を持つ)
  2. Forms 認証は timeout=60 + slidingExpiration=true + requireSSL=true(業務系の入力体験)
  3. 本番デプロイ前に SSL 設定 + 認証 mode + IIS 設定の3点セット確認(チェックリスト化)

このルール化で、認証周りの本番事故が消えた。判断軸を持つ + 書き方を揃えるだけで保守工数と事故率が両方下がるおすすめルールっす。

まとめ

状況 推奨認証方式
イントラ + AD 統合 Windows 認証(web.config 3行 + IIS 設定)
外部公開 + 独自ユーザー Forms 認証 + Cookie + 自前パスワード管理
MFA / 外部プロバイダ Cookie 認証(OWIN + ASP.NET Identity)
Cookie 有効期限 timeout=60 + slidingExpiration=true
SSL 強制 requireSSL=true + httpCookies requireSSL=true
認可制御 [Authorize] 属性 + Role
ユーザー情報取得 User.Identity.Name / User.IsInRole() / ClaimsIdentity
Login Action [AllowAnonymous] でオーバーライド

業務イントラの認証は、「3層分離(認証/認可/セッション)」「判断軸3つ(イントラ/外部公開/MFA)」「SSL 強制」 の3点で9割困らなくなります。業務系イントラの大半は Windows 認証で十分カタが付くので、AD 統合できる環境なら Windows 認証寄せが現実解。次回(連載第7回)は「CSS が効かない時のチェックリスト10項目」を扱うので、認証通過後の UI 表示まわりのトラブルシューティングに進みます。

よくある質問

Q1. 業務イントラの ASP.NET MVC 5 で認証方式はどう選べばいい?

A. 判断軸は3点。イントラ専用 + AD 統合あり → Windows 認証(実装最も簡単・コード変更不要)/ 外部公開 + 独自ユーザー管理 → Forms 認証 or Cookie 認証(パスワード自前管理)/ MFA・外部プロバイダ連携必要 → Cookie 認証(ASP.NET Identity)。業務系イントラの大半は Windows 認証で十分カタが付くので、AD 統合できる環境なら Windows 認証寄せが現実解です。

Q2. Windows 認証で AD が繋がらない時、どこを見ればいい?

A. 3点をチェックします。(1)web.config<authentication mode="Windows"> が設定されているか、(2)IIS のサイト設定で「Windows 認証」が有効・「匿名認証」が無効か、(3)アプリプールの ID がドメインユーザーで AD に問い合わせできるか。AD 接続できないと匿名アクセス扱いで User.Identity.Name が空文字になる「ローカル ID 誤動作」が起きるので、3点を順に確認するのが業務SE 鉄則です。

Q3. Forms 認証の Cookie 有効期限切れで突然ログアウトされる時は?

A. <forms timeout="分数"> の値を確認してください。web.config<authentication><forms timeout="30"> が30分なら、30分操作なしでログアウト。業務系で「画面入力中に Cookie 切れて入力データロスト」事故を防ぐには、timeout="60" 程度に伸ばす + slidingExpiration="true" で操作のたびに有効期限延長する設定がおすすめ。SSL 必須(requireSSL="true")も合わせて確認です。

Q4. [Authorize] 属性の Role 名で大文字小文字の差で詰まる時は?

A. AD の Role 名は大文字小文字を厳密に区別します。[Authorize(Roles = "DOMAIN\\SalesGroup")] と書く時、AD 側の Group 名が SALESGROUP でも salesgroup でも一致しない。AD 側の正式表記をコピペするか、User.IsInRole("...") で一旦テスト出力して確認してから [Authorize] に書くのが業務SE 定番の予防策です。

Q5. Cookie 認証は SSL 必須って本当?

A. 本番運用では SSL 必須です。Cookie 認証は認証トークンを Cookie に乗せて送るので、HTTP(平文)で送信すると Wireshark などで Cookie が抜き取られてなりすましができてしまう。<httpCookies requireSSL="true"> で SSL 必須化、<forms requireSSL="true"> も合わせて設定。開発環境では HTTP も許可することがありますが、本番では SSL 強制が業務SE 鉄則です。

ここまでで認証3方式・認可制御・User.Identity 取得・SSL 強制は押さえた。次回は CSS のトラブルシューティングを扱うので、認証通過後の UI 表示まわりに進みます。連載・WinForms の隣接トピックも貼っておきます。

関連記事

ASP.NET 生存ガイド・連載目次

今回は WinForms 業務SE のための ASP.NET 生存ガイド 全10回の 第6回 です。

以上!

同じ罠でハマってる業務SE仲間いたら、どんどんシェア待ってるぜ!!


この記事が気に入ったら
いいねしてね!

どんどんシェア待ってるぜ!!
  • URLをコピーしました!

コメント

コメントする

CAPTCHA


目次