2012-04-18 3 views
7

.NET (원래 Ruby로 작성)을 사용하여 기존 REST API를 다시 작성해야합니다. 클라이언트의 관점에서 이전 API와 완전히 동일한 방식으로 작동해야합니다. 즉 클라이언트 코드를 변경하지 않아도됩니다. 현재 API에는 기본 인증이 필요합니다. 그래서 기존의 API를 호출하려면 다음 완벽하게 작동합니다 : -ASP.Net 웹 API - 승인 헤더 blank

 var wc = new System.Net.WebClient(); 
     var myCache = new CredentialCache(); 
     myCache.Add(new Uri(url), "Basic", new NetworkCredential("XXX", "XXX")); 
     wc.Credentials = myCache; 
     var returnBytes = wc.DownloadData("http://xxxx"); 

(I 보안상의 이유로 실제 URL/이름/암호 등을 ommit해야했다).

이제 MVC4와 함께 ASP.Net 웹 API를 사용하여 새 API를 작성하고 있습니다. 나는 이상한 문제가있어서 정확히 같은 문제로 다른 사람을 찾을 수 없습니다. 기본 인증을 지원하기 위해, 내가 여기에 가이드 라인을 따랐다 :

http://sixgun.wordpress.com/2012/02/29/asp-net-web-api-basic-authentication/

한 가지, 내가 코드를 넣어 위해 Application_Start에서 Global.asax.cs 파일에서 "핸들러에서 후크"() 이벤트 (내가 짐작했을 정도로 설명되지 않았다).

어쨌든 위 코드를 사용하여 IIS에 배포 한 API를 호출하면 Authorization 헤더가 항상 null이며 위의 내용은 401 Unauthorized로 실패합니다. 그러나이 코드를 사용하여 헤더를 수동으로 설정하면 올바르게 작동합니다. 즉, 인증 헤더가 존재하며 사용자를 인증 할 수 있습니다.

private void SetBasicAuthHeader(WebClient request, String userName, String userPassword) 
    { 
     string authInfo = userName + ":" + userPassword; 
     authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo)); 
     request.Headers["Authorization"] = "Basic " + authInfo; 
    } 
    ....... 
    var wc = new System.Net.WebClient(); 
    SetBasicAuthHeader(request, "XXXX", "XXXX"); 
    var returnBytes = wc.DownloadData("http://xxxx"); 

기존 API의 기존 사용자가 수동으로 헤더를 설정하지 않기 때문에 문제가되지 않지만 나에게 좋지 않습니다.

기본 인증이 작동하는 방식에 대한 초기 요청은 익명이어야하며 클라이언트는 401을 반환하고 클라이언트는 다시 시도해야합니다. 그러나 코드에 중단 점을 넣으면 Antony의 예에서 코드가 다시 부식되지 않습니다. 내 브레이크 포인트가 두 번 치게 될 것으로 예상했다.

어떻게하면이 아이디어를 얻을 수 있습니까?

답변

9

당신은 올바른 행동을 기대하고 있습니다. System.Net.WebClient는 초기 요청시 Authorization 헤더를 자동으로 포함하지 않습니다. 응답이 적절하게 요청 될 때만 적절하게 응답합니다. 내 지식으로는 401 상태 코드 이 적절한 WWW-Authenticate 헤더입니다. 자세한 내용은 herehere을 참조하십시오.

기본 인증 처리기에서 WWW-Authenticate 헤더를 반환하지 않는다고 가정하고 WebClient는 두 번째 요청에서 자격 증명을 보내지 않습니다. Fiddler 또는 이와 유사한 도구에서이를 볼 수 있어야합니다.

핸들러가 이런 일을했다면, 당신은 웹 클라이언트 접근 작업 목격한다 : 당신이 눈치,

//if is not authenticated or Authorization header is null 
return base.SendAsync(request, cancellationToken).ContinueWith(task => 
    { 
     var response = task.Result; 
     response.StatusCode = HttpStatusCode.Unauthorized; 
     response.Headers.Add("WWW-Authenticate", "Basic realm=\"www.whatever.com\""); 
     return response; 
    }); 

//else (is authenticated) 
return base.SendAsync(request, cancellationToken); 

을 당신이 (당신이 다른 방법에했던 것처럼)를 모든 요청에 ​​권한 부여 헤더를 포함하는 경우 귀하의 처리기는 이미 그대로 작동합니다. 따라서 충분할 수도 있습니다. 동일한 방식으로 작동하는 WebClient 및 다른 클라이언트의 경우가 아닙니다.

+0

완벽 해 - 효과가있었습니다. 고맙습니다. – nickthompson