ASP.NET Core MVCで403エラーをクライアントへ返す

 ASP.NET Core MVCに用意されたクラスを使わずに自分で認可状態を実装した場合のやり方(認証、認可の実装は慎重に。できるなら用意されたものを使うのが望ましい)。ぼくはASP.NET Core MVCはフレームワークへの強い縛り付けを要求するものではないというのを試したくて、認証、認可あたりの多少の実装を自分で行った。


 リクエストに対する前処理や後処理を行いたい場合、属性でFilterをつけるといい。コントローラにFilterをつけると、そこに属するアクションではFilterで定義された処理が行われる。これを認可状態のチェックに使う。
 ↓の例は"/Admin"以下にアクセスしたときにAuthorizationFilterで定義された処理が行われるコントローラ。
[AuthorizationFilter]

[Route("Admin")]
public class AdminController : Controller
{ }


AuthorizationFilterはとりあえず以下のように。セッションIDをクッキーに持っているかをチェック。持っていない場合、レスポンスコード403を返したい。
using System;

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using tetsujin.Models;

namespace tetsujin.Filters
{

public class AuthorizationFilter : Attribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
var token = context.HttpContext.Request.Cookies[Session.SESSION_COOKIE];
if (!Session.isAuthorized(token))
{
context.Result = new ForbidResult();
}
}
}
}


 ↑のように書けば、Session.isAuthorizedの真偽で403エラーを返してくれる?No.
context.Result = new ForbidResult();
ではなく
context.Result = new NotFoundResult();
だったら404を返してくれる。違いはForbidResultとNotFoundResultの基底クラスと機能。

 ForbidResultはAuthenticationManager.ForbidAsyncで実行されたもののActionResult。
 NotFoundResultは、StatusCodeResultという、指定のレスポンスコードを返すために用意されたActionResult。
StatusCodeResultを継承したクラスは↓のだけ。
・Microsoft.AspNetCore.Mvc.BadRequestResult
・Microsoft.AspNetCore.Mvc.NoContentResult
・Microsoft.AspNetCore.Mvc.NotFoundResult
・Microsoft.AspNetCore.Mvc.OkResult
・Microsoft.AspNetCore.Mvc.UnauthorizedResult
・Microsoft.AspNetCore.Mvc.UnsupportedMediaTypeResult
・System.Web.Http.ConflictResult
・System.Web.Http.InternalServerErrorResult
https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.statuscoderesult?view=aspnetcore-1.0#derived

 403エラーを返すStatusCodeResultの子クラスはないようだ。
 つーわけで直接StatusCodeResultを、任意のステータスコードでインスタンス化してResultプロパティに入れる。
context.Result = new StatusCodeResult(StatusCodes.Status403Forbidden);
comment: 0