2

次のコードがあるとします。

public class BackupsController : ApiController
{
    private readonly IApiContext context;
    private readonly IBackupService backupService;

    public BackupsController(IApiContext context, IBackupService backupService)
    {
        this.context = context;
        this.backupService = backupService;
    }

    public HttpResponseMessage Get(Guid id)
    {
        if (id == Guid.Empty)
        {
            throw new HttpResponseException(HttpStatusCode.BadRequest);
        }

        IBackupView backup = backupService.Get(id);

        if (backup == null)
        {
            return Request.CreateErrorResponse(HttpStatusCode.NotFound, String.Format("BackupId '{0}' not found.", id));
        }

        if (!IsAuthorizedForBackup(backup))
        {
            throw new HttpResponseException(HttpStatusCode.Forbidden);
        }

        return Request.CreateResponse(HttpStatusCode.OK, backup);
    }

    private bool IsAuthorizedForBackup(IBackupView backup)
    {
        if (context.Principal.IsInRole(MembershipRole.Admin))
        {
            return true;
        }

        if (context.Principal.AllowDataSharing && backup.UserId == context.Principal.UserId)
        {
            return true;
        }

        if (backup.UserId == context.Principal.UserId && backup.Device.Uuid == context.DeviceUuid)
        {
            return true;
        }

        return false;
    }
}

メソッド本体のほとんどすべてを認可フィルターに抽出することは理にかなっていますか? バックアップを 2 回取得せずにそれを行う方法がわかりません。

コントローラーのアクションから承認の問題をどのように分離しますか?

4

2 に答える 2

0

あなたが求めていることは技術的に可能です。アクション フィルターを実装し、オーバーライドされた OnActionExecuted にステータス コードを Forbidden に設定するロジックがあるとします。私はこの方法でそれを行ったわけではなく、実現可能性を調査するための提案にすぎません。OnActionExecuted はアクション メソッドの後に実行され、バックアップにアクセスできます。

別のより良い代替手段は、クレーム ベースの ID を使用し、ClaimsAuthorizationManager のサブクラスを実装することです。CheckAccess(AuthorizationContext) は、アクション クレームとリソース クレームの両方を受け取ります。バックアップに関連する属性は、リソース クレームとして渡すことができます。

于 2013-04-09T18:15:43.297 に答える