2014-03-05 3 views
1

리디렉션 (302) 예측할 수없는 내가 다른 서버에서 웹 API 메서드를 호출 HttpClient를 사용하는 WPF 응용 프로그램을 가지고있다. 그러나 모든 경우에 문제가 발생합니다. 특히 클라이언트 응용 프로그램이 잠자기에서 깨어날 때 (서버가 일시 중지 된 경우), OK : 200 대신 Found : 302가 반환됩니다.는 HttpClient를 & WebAPI

웹 API 메소드는 실제로 무엇이든 할 수 있으며 사용자가 인증되었는지 확인하기 위해 단지 [Authorize] 속성이 있습니다. 사용자가 인증되지 않은 경우 일반적으로, 그것은 내가 ASP.NET 명시 적으로 폼 인증을 사용하지 않는,하지만 리디렉션 클라이언트가 존재하지 않는, login.aspx을 보내고, BTW (404) 을 반환합니다. 여기

코드입니다 : 웹 API 방법 (.NET 4.5) :

[HttpGet] 
public HttpStatusCodeResult IsAuthenticated() 
{ 
    return new HttpStatusCodeResult(System.Net.HttpStatusCode.OK); 
} 

WPF 응용 프로그램 클라이언트 코드 (.NET 4.0) :

public async Task<bool> IsAuthenticated() 
{ 
    try 
    { 
     Uri address = new Uri(AuthUrl); 

     var cookieJar = ReadCookiesFromDisk(COOKIE_FILE); 
     if (cookieJar.Count == 0) 
      return false; 
     var handler = new HttpClientHandler 
     { 
      CookieContainer = cookieJar, 
      UseCookies = true, 
      UseDefaultCredentials = false, 
      AllowAutoRedirect = false 
     }; 

     var client = new HttpClient(handler) 
     { 
      BaseAddress = address 
     }; 

     int timeout = 15000; 
     var task = client.GetAsync(address.ToString()); 
     Task[] tasks = new Task[1]; 
     tasks[0] = task; 
     if (Task.WaitAny(tasks, timeout) != -1) 
     { 
      // task completed within timeout 
      // checking for redirect, but this should not happen!!! 
      HttpResponseMessage response = task.Result; 
      if (response.StatusCode == HttpStatusCode.OK || response.StatusCode == HttpStatusCode.Redirect) 
       return true; 
      else 
       return false; 
     } 
     else 
     { 
      // timeout logic 
      return false; 
     } 
    } 
    catch (Exception e) 
    { 
     EventLogger.Log(e); 
     return false; 
    } 
} 

클라이언트 인증 코드 :

public async Task<string> Login(string data) 
     { 
      try 
      { 
       Uri address = new Uri(LoginUrl); 
       HttpContent content = new StringContent(data, Encoding.UTF8); 

       content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"); 
       var cookieJar = ReadCookiesFromDisk(COOKIE_FILE); 
       var handler = new HttpClientHandler 
       { 
        CookieContainer = cookieJar, 
        UseCookies = true, 
        UseDefaultCredentials = false, 
        AllowAutoRedirect = false 
       }; 

       var client = new HttpClient(handler) 
       { 
        BaseAddress = address 
       }; 
       HttpResponseMessage response = await client.PostAsync(address.ToString(), content); 
       response.EnsureSuccessStatusCode(); 
       string body = await response.Content.ReadAsStringAsync(); 

       Uri uri = new Uri(UrlBase); 
       var responseCookies = cookieJar.GetCookies(uri); 
       if (responseCookies[".ASPXAUTH"] != null) 
        WriteCookiesToDisk(COOKIE_FILE, cookieJar); 
       return body; 
      } 
      catch (Exception e) 
      { 
       return e.ToString(); 
      } 
     } 

서버 :

비동기를 사용할 때 문 위의

HttpResponseMessage response = await client.PostAsync(address.ToString(), content).ConfigureAwait(false); 

에 코드

HttpResponseMessage response = await client.PostAsync(address.ToString(), content); 

다음3210

public JsonResult LogOn(string userInfo) 
     { 
      JavaScriptSerializer serializer = new JavaScriptSerializer(); 
      LogOnModel model = serializer.Deserialize<LogOnModel>(userInfo); 
      JsonMessage error = null; 
      if (ModelState.IsValid) 
      { 
       try 
       { 
        if (WebSecurity.Login(model.UserName, model.Password, persistCookie: model.RememberMe)) 
        { 
         if (WebSecurity.IsConfirmed(model.UserName)) 
         { 
          if (model.RememberMe) 
           Response.Cookies[0].Expires = DateTime.Now.AddDays(30); 
          else 
           Response.Cookies[0].Expires = DateTime.Now.AddDays(7); 

          var person = Dc.People.FirstOrDefault(x => x.UserName == model.UserName); 
          string fullName = string.Empty; 
          string email = string.Empty; 
          if (person != null) 
          { 
           fullName = string.Format("{0} {1}", person.FirstName, person.LastName); 
           email = person.Email; 
           //fill the session to create the session cookie 
           Session["1"] = 1; 
          } 
          var message = new { FailCount = 0, Message = WebSecurity.GetUserId(model.UserName).ToString(), Success = true, SuccessCount = 0, RedirectUrl = "#/conversations/priority", Name = fullName, UserEmail = email, UserHandle = model.UserName, UserAvatar = person.Avatar }; 
          return Json(message); 
         } 
         else 
         { 
          error = new JsonMessage { FailCount = 0, Message = "Your aren't authorised to login", Success = false, SuccessCount = 0 }; 
          TempData["Error"] = "Your are not authorised to login"; 
          return Json(error); 

         } 
        } 
        else 
        { 

         TempData["Error"] = "The user name or password provided is incorrect."; 
         error = new JsonMessage { FailCount = 0, Message = "The user name or password provided is incorrect.", Success = false, SuccessCount = 0 }; 
         return Json(error); 
        } 
       } 
       catch (Exception ex) 
       { 
        TempData["Error"] = ex.Message; 
        error = new JsonMessage { FailCount = 0, Message = ex.Message, Success = false, SuccessCount = 0 }; 
       } 
      } 

      return Json(error); 
     } 
+0

어떻게 WPF 응용 프로그램은 일반적으로 서버에서 인증합니까? 컴퓨터가 절전 모드에있는 동안 인증 쿠키가 만료되어 웹 API가 클라이언트에 다시 인증하도록 지시 할 가능성이 있습니다 (리디렉션을 사용하는 양식 인증 방식에서). 위의 샘플에서 상태 코드를 확인할 때 302가 성공적으로 인증 된 것으로 간주되는 이유는 무엇입니까? 당신은 302를 얻는다면 웹 API에서 정상적으로 인증 할 수 있습니까? 다음 링크는 웹 API의 인증에 대한 몇 가지 샘플을 제공합니다 (http://www.asp.net/web-api/overview/security). – Markus

+0

302가 성공하면 임시 수정 사항이지만 루트 문제는 해결되지 않습니다. 즉, 서버에서 반환 된 쿠키의 유효 기간은 30 일이지만 302는 훨씬 빨라집니다 (당일). –

+0

클라이언트와 서버 모두에서 인증하는 데 사용할 코드를 표시 할 수 있습니까? – Markus

답변

-1

변경 언젠가 교착 상태 문제를 보여줍니다. 따라서 비동기 작업에 대해 false를 대기하도록 구성하면 올바른 방식으로 작동합니다.

관련 문제