2010-05-30 5 views
5

사용자가 항목에 대한 입찰을 시작하기 전에 로그인해야하는 ASP.NET MVC 2.0 응용 프로그램을 작성 중입니다. 나는 actionfilter를 사용하여 사용자가 로그인했는지 확인하고, 그렇지 않은 경우 로그인 페이지로 보내고 반환 URL을 설정합니다. 아래는 액션 필터에서 사용하는 코드입니다. 내 로그온 컨트롤러에서리디렉션 후 ReturnURL에 대한 HttpPost

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

내 문제는이 항상 내 원래 반면 가져 오기 (HttpGet) 요청을 사용하는 것입니다 제출은 게시물 (HttpPost)이었으며 항상 게시물이어야합니다. 누구든지 올바른 HttpMethod가 사용되도록 HttpMethod 나 다른 해결 방법을 포함하여이 URL을 전달하는 방법을 제안 할 수 있습니까?

답변

7

쉬운 방법은 없습니다. 인증되지 않은 사용자를 로그인 페이지로 리디렉션하는 것이 좋습니다. 일부 URL에 게시 할 때가 아니라 인증 된 URL에 POST 할 양식을 요청할 때입니다.

인증되지 않은 사용자에게 표시 할 양식이 사이트의 인증 된 부분에 게시된다는 것을 알고 있으면 양식을 제출하지 마십시오. 이 양식을 요청하면 인증을 위해 로그인 페이지로 리디렉션되고 일단 인증되면 원래 양식으로 리디렉션됩니다. 이렇게하면 인증 된 사용자 만 보호 된 리소스에 POST하도록 할 수 있습니다.

단순한 401 상태 코드를 자격 증명을 제공하지 않는 요청으로 반환하는 자동화 된 POST 요청 (봇, 웹 서비스 등)에 관한 것만으로는 충분하지 않습니다.

7

나는 왜 당신은 입찰가가 POST 일 뿐이므로 인증을 원한다고 생각합니다. 입찰에는 로그인이 필요하지만 로그인하지 않은 사용자는 입찰 페이지를 볼 수 있습니다. 이베이/아마존 등처럼. 사용자를 기준으로 지불 또는 조치가 필요할 때까지 모든 내용이 표시됩니다.

Request.RequestTypePOST 인 경우 속성을 변경하여 Request.UrlReferrer을 로그인 페이지로 되돌릴 수 있습니다. 그런 다음 경매 페이지로 리디렉션되고 일단 로그인하면 입찰을 다시 클릭 할 수 있습니다. 특정 필드 (예 : 금액)를 UrlReferrer과 함께 전달할 수 있으므로 금액 입력란을 다시 채울 수 있습니다. 경매 페이지. 해당 필드는 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

두 컨트롤러 이름이 같은 방법하지만, 게시물에 대한 GET에 대한 다른 하나를 쓰고, TempData (또는 세션)에서 get 메소드의 ReturnUrl을 기억하고 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"); 
       } 
      } 

......

처음으로 페이지에 도착했을 때 그것은 defintely입니다 get 액션을 사용하여 데이터를 서버에 게시하십시오.

Request.UrlReferrer에서 전체 URL을 가져올 수 있다고 생각합니다.