6

アイテムに入札する前にユーザーがログインする必要がある ASP.NET MVC 2.0 アプリケーションを作成しています。私は actionfilter を使用して、ユーザーがログインしていることを確認し、ログインしていない場合はログイン ページに送信し、リターン URL を設定しています。以下は、アクションフィルターで使用するコードです。

if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
    filterContext.Result = new RedirectResult(String.Concat("~/Account/LogOn","?ReturnUrl=",filterContext.HttpContext.Request.RawUrl));
    return;
}

ログオン コントローラーで、ユーザーの資格情報を検証し、サインインしてリターン URL にリダイレクトします。

FormsAuth.SignIn(userName, rememberMe);
if (!String.IsNullOrEmpty(returnUrl))
{
    return Redirect(returnUrl);
}

私の問題は、これが常に Get (HttpGet) 要求を使用することですが、元の送信は投稿 (HttpPost) であり、常に投稿である必要があります。HttpMethod を含むこの URL を渡す方法や、正しい HttpMethod が確実に使用されるようにするための回避策を誰かが提案できますか?

4

3 に答える 3

8

これを行う簡単な方法はありません。認証されていないユーザーをログインページにリダイレクトすることをお勧めします。URLに投稿するときではなく、認証されたURLにPOSTするフォームをリクエストするときです。

認証されていないユーザーに提示しているフォームがサイトの認証された部分にPOSTされることがわかっている場合は、フォームを提示しないでください。このフォームが要求されたら、認証のためにログインページにリダイレクトし、認証されると元のフォームにリダイレクトします。このようにして、認証されたユーザーのみが保護されたリソースにPOSTするようにします。

自動化されたPOSTリクエスト(ボット、Webサービスなど)に関する限り、資格情報を提供しないリクエストに単純な401ステータスコードを返すだけで十分です。

于 2010-05-30T19:18:48.247 に答える
7

POST認証を入札アクションのみにしたい理由がわかると思います。入札にはログインが必要ですが、ログインしていないユーザーはオークション ページを見ることができます。ebay/amazon などと同じように、ユーザーに基づいて支払いまたはアクションが必要になるまで、すべてが表示されます。

がの場合、代わりにRequest.UrlReferrerをログイン ページに返すように属性を変更できます。次に、彼らはオークション ページにリダイレクトされ、ログインすると再度入札をクリックできます。たとえば、金額などの特定のフィールドを渡すこともできます。これにより、オークションに到着したときに金額フィールドを再入力できます。ページ。コレクションからそのフィールドを取得できます。Request.RequestTypePOSTUrlReferrerRequest.Form

// in usage...    
[RequireLogin(AdditionalFields="amount,someotherfield")]
[HttpPost]
public ActionResult Bid(.....)

// the attribute 
class RequireLoginAttribute : ActionFilterAttribute
{
    public string AdditionalFields { get; set; }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            var returnUrl = filterContext.HttpContext.Request.RawUrl;
            if (filterContext.HttpContext.Request.RequestType == "POST")
            {
                returnUrl = filterContext.HttpContext.Request.UrlReferrer.PathAndQuery;
                // look for FORM values in request to append to the returnUrl
                // this can be helpful for a good user experience (remembering checkboxes/text fields etc)
            }

            filterContext.Result = new RedirectResult(String.Concat("~/Account/LogOn", "?ReturnUrl=", returnUrl));
            return;
        }
        base.OnActionExecuting(filterContext);
    }
}
于 2010-06-01T14:46:17.080 に答える
2

同じ名前の 2 つの Controller メソッドを記述できますが、1 つは get 用、もう 1 つは post 用です。TempData (またはセッション) の get メソッドで ReturnUrl を覚えておき、post 要求が到着したときに TempData から ReturnUrl を取得します。

コードは次のようになります。

    public ActionResult LogOn(string returnUrl)
    {
        if (!string.IsNullOrEmpty(returnUrl))
        {
            TempData["ReturnUrl"] = returnUrl;
        }
        return View();
    }

    [HttpPost]
    public ActionResult LogOn(LogOnModel model, FormCollection collecton)
    {
        if (ModelState.IsValid)
        {
            AuthenticationResult logonStatus = TransactionScriptFactory.GetTransactionScript<UserTransactionScripts>()
                                                                       .LogOn(model.Email, model.Password);

            if (logonStatus.AuthResult == AuthResultEnum.Success)
            {
                FormsService.SignIn(logonStatus.User.UserId, logonStatus.User.NickName, false);

                object returnUrl = string.Empty;
                TempData.TryGetValue("ReturnUrl", out returnUrl);
                string returnUrlStr = returnUrl as string;
                if (!string.IsNullOrEmpty(returnUrlStr))
                {
                    return Redirect(returnUrlStr);
                }
                else
                {
                    return RedirectToAction("Index", "Home");
                }
            }

……

get アクションを使用して最初にページに到達し、次にデータをサーバーに投稿するのは間違いありません。

Request.UrlReferrer から URL 全体を取得することもできると思います。

于 2010-11-20T07:30:15.530 に答える