ユーザーがログインしてデータを管理できるMVC 3アプリを作成しています。ユーザーが他のユーザーのデータを閲覧したり、改ざんしたりできないようにしたい。私の最初の本能は、次のように各アクション メソッドで関連するオブジェクトへのアクセスを確認することでした。
public ActionResult ShowDetails(int objectId)
{
DetailObject detail = _repo.GetById(objectId);
if (detail.User.UserID != (Guid)Membership.GetUser().ProviderUserKey)
{
return RedirectToAction("LogOff", "Account");
}
}
これは問題なく動作しますが、オブジェクトの承認コードを AuthorizeAttribute から派生したカスタムの Authorize 属性に入れ、それをコントローラーに適用する方がよいのではないかと考えました。残念ながら、カスタムの Authorize 属性内からアクション メソッドのパラメーターにアクセスする方法を見つけることができませんでした。代わりに、着信 objectId にアクセスする唯一の方法は、httpContext.Request または filterContext.RequestContext.RouteData.Values を調べることです。
public class MyAuthorizeAttribute : AuthorizeAttribute
{
private int _objectId = 0;
private IUnitOfWork _unitOfWork;
public MyAuthorizeAttribute(IUnitOfWork uow)
{
_unitOfWork = uow;
}
public override void OnAuthorization(AuthorizationContext filterContext)
{
int.TryParse((string) filterContext.RequestContext.RouteData.Values["id"], out _objectId);
base.OnAuthorization(filterContext);
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
int objectId = 0;
if (httpContext.Request.Params.AllKeys.Contains("id", StringComparer.InvariantCultureIgnoreCase))
{
int.TryParse(httpContext.Request[idKey], out objectId);
}
if (objectId != 0)
{
if (!IsAuthorized(objectId, httpContext.User.Identity.Name))
{
return false;
}
}
if (_objectId != 0)
{
if (!IsAuthorized(objectId, httpContext.User.Identity.Name))
{
return false;
}
}
return base.AuthorizeCore(httpContext);
}
private bool IsAuthorized(int objectId, string userName)
{
DetailObject detail;
detail = _unitOfWork.ObjectRepository.GetById(objectId);
if (detail == null)
{
return false;
}
if (userName != detail.User.UserName)
{
return false;
}
return true;
}
}
このアプローチは非常に不格好だと思います。RouteData または Request オブジェクトをいじる必要は本当にありません。モデル バインディングはすでに RouteData と Request から関連データを引き出しているため、アクション メソッドのパラメーターにアクセスできるようにすると、はるかにクリーンになります。
カスタム アクション フィルター (詳細はこちら)からアクション メソッドのパラメーターにアクセスできることはわかっていますが、データ承認コードを承認フィルターに配置するべきではありませんか? Authorize フィルターの例が増えれば増えるほど、役割を処理するためだけに意図されているという印象を受けます。
私の主な質問は、カスタム Authorize 属性からアクション メソッドのパラメーターにアクセスするにはどうすればよいですか?