0

move.UserId が currentUserId と等しくない場合は例外を構築しようとし、アクションにリダイレクトするか、move.UserId が currentUserId と等しい場合はビューを返します。

ここのコードを参照してください:

public ActionResult Details(int id)
    {
        MembershipUser currentUser = Membership.GetUser();
        Guid currentUserId = (Guid)currentUser.ProviderUserKey;
        Move move = db.Moves.Where(m => m.UserId == currentUserId)
            .FirstOrDefault();

            if (currentUser != null && currentUser.ProviderUserKey != null && currentUser.IsApproved)
            {
                if (move.UserId == currentUserId)
                {
                    return View(move);
                }
            }

        return RedirectToAction("Oops", new RouteValueDictionary(
 new { controller = "Account", action = "Oops", area = "", id = UrlParameter.Optional }));
    }

Move/(int) を戻す URL に結び付けて、ユーザーがこれを move.UserId != currentUserId の移動を返す (int) に変更すると、リダイレクトも行います。現在、URL を変更して他の人の動きを取得できます。

マイコントローラー

    public ViewResult Index()
    {
        if (User.Identity.IsAuthenticated)
        {
            MembershipUser currentUser = Membership.GetUser();
            Guid currentUserId = (Guid)currentUser.ProviderUserKey;
            if (currentUser != null && currentUser.ProviderUserKey != null && currentUser.IsApproved)
            {
                var results = db.Moves.Where(move => move.UserId == currentUserId)
                    .ToList();
                return View(results);
            }
        }
        return View(db.Moves.ToList());
    }

    [ClientValidation]
    public ActionResult Details(Move move)
    {
        return View(move);
    }

私の見解

@model MovinMyStuff.Domain.Entities.Move
@{
ViewBag.Title = "Details";
    }
<div>

    @Html.DisplayFor(model => model.StartCity),
    @Html.DisplayFor(model => model.StartState)
    @Html.DisplayFor(model => model.StartZip) -
    @Html.DisplayFor(model => model.EndCity),
    @Html.DisplayFor(model => model.EndState)
    @Html.DisplayFor(model => model.EndZip)
</div>
<fieldset>
    <div class="job-details">
    @Html.HiddenFor(model => model.MoveId)
    @Html.HiddenFor(model => model.UserId)
        <ul class="distance">
            <li>
                <div>
                    Distance</div>
            </li>
            <li>1,978.6 Miles</li>
        </ul>
        <ul class="address-wrapper">
            <li>
                <ul class="address from">
                    <li>
                        <div>
                            From</div>
                    </li>
                    <li><span>Address: </span>
                        @Html.DisplayFor(model => model.StartStreetNumber)
                        @Html.DisplayFor(model => model.StartStreetName)
                    </li>
    ...
    </fieldset>
4

2 に答える 2

1

最初にテストすることは、LINQ クエリが Move を返したかどうかです。.Whereそうでない場合は、クエリに現在のユーザーの動きのみに制限する句があるため、ユーザーが彼に属さない動きを表示しようとしていることを意味します。

現在、NullReferenceException が発生します。

そう:

[Authorize]
public ActionResult Details(int id)
{
    MembershipUser currentUser = Membership.GetUser();
    Guid currentUserId = (Guid)currentUser.ProviderUserKey;
    Move move = db.Moves.Where(m => m.UserId == currentUserId && m.MoveId == id).FirstOrDefault();
    if (!currentUser.IsApproved || move == null)
    {
        // the user is trying to display a move that doesn't belong to him =>
        // redirect him or throw a 403 HTTP exception
        return RedirectToAction("Oops", new RouteValueDictionary(new { controller = "Account", action = "Oops", area = "", id = UrlParameter.Optional }));
    }

    // at this stage we can grant access to the user because we know
    // that he is authenticated, he is approved and that the move he is
    // trying to consult belongs to him
    return View(move);
}

多くのコントローラ アクションでこのロジックを繰り返す必要がある場合は、カスタム Authorize 属性を記述する価値があることは明らかです。

[EnsureUserAllowedToConsultMove]
public ActionResult Details(Move move)
{
    // at this stage we can grant access to the user because we know
    // that he is authenticated, he is approved and that the move he is
    // trying to consult belongs to him
    return View(move);
}

このカスタム Authorize 属性は次のようになります。

public class EnsureUserAllowedToConsultMoveAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        var authorized = base.AuthorizeCore(httpContext);
        if (!authorized)
        {
            return false;
        }

        if (!httpContext.Request.RequestContext.RouteData.Values.ContainsKey("id"))
        {
            return false;
        }

        var id = (string)httpContext.Request.RequestContext.RouteData.Values["id"];
        var currentUser = Membership.GetUser();
        var currentUserId = (Guid)currentUser.ProviderUserKey;
        return db.Moves.Any(m => m.UserId == currentUserId && m.MoveId == id);
    }

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        var values = new RouteValueDictionary(new
        {
            controller = "account",
            action = "oops",
            area = ""
        });
        filterContext.Result = new RedirectToRouteResult(values);
    }
}

これで、問題を分離し、承認ロジックをカスタム承認属性に外部化することができました。コントローラーをそのようなコードで汚染する必要はもうありません。

于 2012-06-28T08:54:20.580 に答える
0

このタイプの作業には Authorize フィルターを使用する必要があります。詳細については、こちらをご覧くださいASP.NET MVC カスタム認証

于 2012-06-28T08:51:52.553 に答える