.NET Framework 4.5 から追加された SuppressFormsAuthenticationRedirect プロパティが便利でした。フォーム認証を設定している ASP.NET MVC アプリと同じプロジェクトに ASP.NET Web API を実装した場合、Web API の Controller のアクションメソッドで HttpStatusCode.Unauthorized(401)を返しても、クライアント側には Location ヘッダーにログインページの URL が設定された HttpStatusCode.Found(302)に書き変えられた結果が返されます。Web API でこの動作だと都合が悪いときには、SuppressFormsAuthenticationRedirect プロパティに true をセットすると、HttpStatusCode.Unauthorized(401)を返すことができます。
前準備
Visual Studio から、ASP.NET Web API のプロジェクトを作成し、MVC アプリケーションにフォーム認証を設定します。
まず、HomeController クラスに Authorize 属性を付加します。
#HomeController.cs [AllowAnonymous] [Authorize] public class HomeController : Controller { public ActionResult Index() { return View(); } }
Web.config でフォーム認証を有効にします。
#Web.config <system.web> <authentication mode="Forms"> <forms loginUrl="/Account/Login/" /> </authentication> </system.web>
ログインとログアウトのアクションメソッドをもつ AccountController クラスと ビュー を実装します。
#AccountController.cs [AllowAnonymous] public class AccountController : Controller { public ActionResult Login() { return View(); } [HttpPost] [ValidateAntiForgeryToken] public ActionResult Login(string model) { FormsAuthentication.SetAuthCookie("Guest", false); return RedirectToAction("Index", "Home"); } public ActionResult Logout() { FormsAuthentication.SignOut(); return RedirectToAction("Login", "Account"); } }
#Login.cshtml @{ ViewBag.Title = "Login"; } @using (Html.BeginForm()) { @Html.AntiForgeryToken() <div class="form-group"> <input type="submit" value="Login" class="btn btn-default" /> </div> }
HttpStatusCode.Unauthorized(401)を返す Web API の TestController クラスを実装します。
#TestController.cs public class TestController : ApiController { [Route("api/test")] public IHttpActionResult Get() { return StatusCode(HttpStatusCode.Unauthorized); } }
結果確認
プログラムを実行し、IE の F12 開発者ツールでキャプチャしてみます。GET api/test をリクエストすると、HttpStatusCode.Found(302)が返されてログインページにリダイレクトされていることが分かります。
SuppressFormsAuthenticationRedirect プロパティに true をセットするように変更し、再度プログラムを実行します。
#TestController.cs public class TestController : ApiController { [Route("api/test")] public IHttpActionResult Get() { HttpContext.Current.Response.SuppressFormsAuthenticationRedirect = true; return StatusCode(HttpStatusCode.Unauthorized); } }
今度は、HttpStatusCode.Unauthorized(401)が返されるようになりました。
まとめ
いろいろと調べていると、FormsAuthenticationModule に書き換えられたステータスをカスタムモジュールで再度書き換える方法もありました。
.NET Framework 4.5 以降であれば、SuppressFormsAuthenticationRedirect プロパティを使うのが便利そうです。