みなさんこんにちは!ヒロポンです!!
今回は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側の設定:
- サイトの認証で「Windows認証」を有効
- 「匿名認証」を無効
- アプリプールの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();
}
}
ポイント:
- コード変更ゼロ(
web.configとIIS設定のみ) - SSO自動(ドメイン参加PCからアクセスすると自動でログイン状態)
User.Identity.Nameで社員番号取得(ADアカウント名)- 業務系イントラの大半はこれで完結
業務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");
}
}
ポイント:
FormsAuthentication.SetAuthCookie(userId, persistent)でCookie発行<forms timeout="60" slidingExpiration="true">で60分操作なしでログアウト、操作で延長requireSSL="true"でSSL必須化(本番運用の鉄則)- パスワードハッシュ化は自前実装(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(...);
}
}
ポイント:
Install-Package Microsoft.AspNet.Identity.Owinで導入UseCookieAuthenticationでCookie認証ミドルウェア登録SecurityStampValidatorでセキュリティスタンプ検証(パスワード変更時に既存セッション無効化)- 外部プロバイダ連携が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(); //ログイン必須
}
ポイント:
[Authorize]で未ログイン排除(LoginUrlにリダイレクト)[Authorize(Roles = "...")]でRole制御- AD GroupもRoleとして使える(Windows認証時)
[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.NameがIIS 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行ルールにまとめた:
- イントラ+ ADあり= Windows認証寄せ、外部公開= Forms認証、MFA = Cookie認証(判断軸を持つ)
- Forms認証はtimeout=60 + slidingExpiration=true + requireSSL=true(業務系の入力体験)
- 本番デプロイ前に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の隣接トピックも貼っておきます。
関連記事
- ControllerはWinFormsのForm_Load拡張版だと理解する— ASP.NET MVC 5業務SE入門 —連載第2回・Action内部で
User.Identityを扱う基礎に効く - ASP.NET MVC 5で使えるORM 3択— EF6 / Dapper / ADO.NETの業務SE視点比較 —連載第4回・ASP.NET IdentityのDB管理を整理する時に効く
- ASP.NET MVC 5でDIは業務系に要るのか—入れない派の論点も書く —連載第5回・認証サービスをDIコンテナで注入する時に効く
ASP.NET生存ガイド・連載目次
今回はWinForms業務SEのためのASP.NET生存ガイド全10回の第6回です。
- 第1回: WinFormsのFormとRazor Viewの対応関係を業務SEが一日で腹落ちさせる
- 第2回: ControllerはWinFormsのForm_Load拡張版だと理解する— ASP.NET MVC 5業務SE入門
- 第3回: ASP.NET MVC 5のルーティングをWinFormsのForm切替で理解する
- 第4回: ASP.NET MVC 5で使えるORM 3択— EF6 / Dapper / ADO.NETの業務SE視点比較
- 第5回: ASP.NET MVC 5でDIは業務系に要るのか—入れない派の論点も書く
- 第6回(今回):業務イントラの認証— Windows認証/ Forms認証/ Cookieの使い分け←イマココ
- 第7回: CSSが効かない時のチェックリスト10項目(公開予定)
- 第8回: IISデプロイ—オンプレ業務系の現実(公開予定)
- 第9回: ASP.NET MVC 5トラブルシューティング・チェックリスト20項目(公開予定)
- 目次(最終回): WinForms業務SEのためのASP.NET生存ガイド・全体目次(公開予定)
以上!
同じ罠でハマってる業務SE仲間いたら、どんどんシェア待ってるぜ!!
執筆者
バイブス父さん — 業務 SE 7 年 (正社員 2 / フリーランス 5)。 現職は SEO 直轄部の AI アドバイザー兼 PL、 副業で中小 SIer の CTO。 SES 複数社・フリーランスエージェント複数経由の経験ベースで「業務 SE 視点」 の技術 + キャリア記事を書いています。
🐦 X: @hiro_progra0524 (日々の現場メモ更新中)
📝 About Me で経歴詳細を見る


コメント