2010-05-30 33 views
5

Tôi đang viết ứng dụng ASP.NET MVC 2.0 yêu cầu người dùng đăng nhập trước khi đặt giá thầu trên một mặt hàng. Tôi đang sử dụng bộ lọc hành động để đảm bảo rằng người dùng đã đăng nhập và, nếu không, hãy gửi họ đến trang đăng nhập và đặt url trả về. Dưới đây là mã tôi sử dụng trong bộ lọc hành động của tôi.HttpPost to ReturnURL sau khi chuyển hướng

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

Trong điều khiển đăng nhập của tôi, tôi xác nhận các thông tin người dùng sau đó đăng ký chúng trong và chuyển hướng đến url trở

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

Vấn đề của tôi là điều này sẽ luôn luôn sử dụng một yêu cầu GET (HttpGet) trong khi ban đầu của tôi gửi là một bài đăng (HttpPost) và luôn luôn là một bài đăng. Bất cứ ai có thể đề xuất một cách để vượt qua URL này bao gồm HttpMethod hoặc bất kỳ workaround để đảm bảo rằng HttpMethod chính xác được sử dụng?

Trả lời

7

Không có cách nào dễ dàng để thực hiện việc này. Tôi khuyên bạn nên chuyển hướng người dùng chưa được xác thực đến trang đăng nhập chứ không phải khi đăng lên một số URL nhưng khi yêu cầu biểu mẫu sẽ POST tới URL được xác thực.

Nếu bạn biết rằng biểu mẫu mà bạn đang trình bày cho người dùng chưa được xác thực sẽ POST tới phần được xác thực của trang web, tốt, không hiển thị cho anh biểu mẫu. Khi biểu mẫu này được yêu cầu, chỉ cần chuyển hướng đến trang đăng nhập để xác thực và một khi chuyển hướng được xác thực sang biểu mẫu ban đầu. Bằng cách này, bạn sẽ đảm bảo rằng chỉ những người dùng được xác thực mới được POST vào tài nguyên được bảo vệ.

Theo yêu cầu POST tự động (bot, dịch vụ web, ...) trả lại mã trạng thái 401 đơn giản cho các yêu cầu không cung cấp bằng chứng xác thực thì quá đủ.

7

Tôi nghĩ rằng tôi nhận được lý do tại sao bạn muốn xác thực chỉ được thực hiện trên hành động giá thầu POST. Giá thầu yêu cầu thông tin đăng nhập, nhưng bất kỳ người dùng nào không đăng nhập đều có thể xem trang đấu giá. Cũng giống như ebay/amazon vv Mọi thứ đều hiển thị cho đến khi bạn yêu cầu thanh toán hoặc hành động dựa trên người dùng.

Thay vào đó, bạn có thể thay đổi thuộc tính của mình để trả lại Request.UrlReferrer thành trang đăng nhập nếu Request.RequestTypePOST. Sau đó, họ sẽ được chuyển hướng đến trang đấu giá và có thể nhấp vào giá thầu một lần nữa khi họ đăng nhập. Bạn thậm chí có thể chuyển một trường nhất định, với số tiền là UrlReferrer để bạn có thể điền lại trường số tiền khi họ truy cập vào trang đấu giá. Bạn có thể lấy trường đó từ bộ sưu tập Request.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); 
    } 
} 
2

Bạn có thể viết hai phương pháp điều khiển có cùng tên, nhưng người ta cho get và một cho bưu điện, và nhớ ReturnUrl trong phương thức get trong TempData (hoặc khóa), và sau đó nhận được ReturnUrl từ TempData khi bài yêu cầu đến:

mã này có thể trông như sau:

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"); 
       } 
      } 

......

Đó là defintely khi bạn lần đầu tiên đến với trang bằng cách sử dụng get action, sau đó đăng dữ liệu lên máy chủ.

Tôi nghĩ bạn cũng có thể nhận được toàn bộ url từ Request.UrlReferrer.

Các vấn đề liên quan