2011-05-01 8 views
8

MVC3 응용 프로그램이 있고 컨트롤러 동작이 [Authorize] 특성을 사용하여 보호됩니다. 지금까지는 형식 승인이 훌륭했습니다. 이제 JSON API를 내 애플리케이션에 추가하여 브라우저가 아닌 클라이언트가 일부 작업에 액세스 할 수있게하려고합니다.JSON을 반환하는 ASP.NET MVC 컨트롤러 보안 조치

'올바른 디자인'을 찾는 데 문제가 있습니다.

1) 각 사용자는 비밀 API 키를 가지고 있습니다.

2) 사용자 ID 5는 http://myapp.com/foocontroller/baraction/5?param1=value1&param2=value2&secure_hash=someValue으로 전화합니다. 여기서 secure_hash는 사용자의 비밀 API 키가 추가 된 param1 및 param2의 SHA1 해시입니다.

2)/foocontroller/baraction은 [CustomAuthorize]로 장식됩니다. 이것은 요청이 JSON으로 들어오는지를 확인하는 AuthorizeAttribute의 구현 일 것이다. 일치하면 해시를 검사하여 일치하는지 확인합니다. 그렇지 않으면 요청이 HTML 인 경우 기존 승인을 호출합니다.

정상적으로 작동하는지 확실하지 않습니다. 쿼리 문자열에 보안 해시를 전달하는 것이 일반적입니까? 아니면 HTTP 헤더로 전달해야합니까? 비밀 API 키를 사용하여 만든 해시 대신 HTTP 기본 인증을 사용하는 것이 더 낫습니까?

ASP.NET MVC를 사용하여 웹 API를 만든 사람의 팁을 환영합니다!

답변

11

요청 본문에 사용자 이름과 비밀번호와 함께 비밀 API 키를 전달합니다. 권한이 부여되면 토큰이 생성되고 클라이언트는 Authorization 헤더에 토큰을 전달해야합니다. 이것은 각 요청에 대해 기본 컨트롤러에서 확인됩니다.

  1. 클라이언트는 인증 토큰을 반환하는 myapp.com/authorize를 호출합니다.
  2. 클라이언트가 인증 토큰을 로컬에 저장합니다.
  3. 클라이언트는 인증 헤더에 authtoken과 함께 myapp.com/anycontroller를 호출합니다.

AuthorizeController는 컨트롤러를 상속합니다. Anycontroller는 인증 코드를 수행하는 사용자 지정 기본 컨트롤러에서 상속합니다.

이 예제에서는 POST 요청을 모든 컨트롤러의 POST라는 ActionResult에 전달하는 다음 경로가 필요합니다. 나는 이것을 당신이 일반적인 생각을 가능한 한 많이 단순화하기 위해 직접 입력하고있다. 잘라 내기 및 붙여 넣기 및 작동 :)

routes.MapRoute(
    "post-object", 
    "{controller}", 
    new { controller = "Home", action = "post" {, 
    new { httpMethod = new HttpMethodConstraint("POST")} 
); 

귀하의 인증 컨트롤러는이

public class AuthorizationController : Controller 
{ 
    public ActionResult Post() 
    { 
     string authBody; 
     var request = ControllerContext.HttpContext.Request; 
     var response = ControllerContext.HttpContext.Response; 

     using(var reader = new StreamReader(request.InputStream)) 
      authBody = reader.ReadToEnd(); 

     // authorize based on credentials passed in request body 
     var authToken = {result of your auth method} 

     response.Write(authToken); 

    } 
} 

귀하의 다른 컨트롤러가 기본 컨트롤러

public class BaseController : Controller 
{ 
    protected override void Execute(RequestContext requestContext) 
    { 
     var request = requestContext.HttpContext.Request; 
     var response = requestContext.HttpContext.Response; 

     var authToken = Request.Headers["Authorization"]; 

     // use token to authorize in your own method 
     var authorized = AmIAuthorized(); 

     if(authorized = false) { 
      response.StatusCode = 401; 
      response.Write("Invalid token"); 
      return;    
     } 

     response.StatusCode = 200; // OK 

     base.Execute(requestContext); // allow inheriting controller to continue 

    } 
} 

샘플에서 상속 사용할 수 있습니다 기대하지 마십시오 API 호출 코드

public static void ExecutePostRequest(string contentType) 
     { 
      request = (HttpWebRequest)WebRequest.Create(Uri + Querystring); 
      request.Method = "POST"; 
      request.ContentType = contentType; // application/json usually 
      request.Headers["Authorization"] = token; 

      using (StreamWriter writer = new StreamWriter(request.GetRequestStream())) 
       writer.Write(postRequestData); 

      // GetResponse reaises an exception on http status code 400 
      // We can pull response out of the exception and continue on our way    
      try 
      { 
       response = (HttpWebResponse)request.GetResponse(); 
      } 
      catch (WebException ex) 
      { 
       response = (HttpWebResponse)ex.Response; 
      } 
      finally 
      { 
       using (StreamReader reader = 
        new StreamReader(response.GetResponseStream())) 
        responseText = reader.ReadToEnd(); 
       httpcontext = HttpContext.Current; 
      } 
     } 
+0

제이슨, 나는 더 자세한 것을 좋아할거야. 저는 MVC (RoR 배경)에 익숙하지 않아서 속성의 권한 부여 방식이 어색합니다. 감사! –

+0

고맙습니다 Jason! 요청 본문에 사용자 이름과 비밀번호와 함께 비밀 API 키를 전달하는 방법은 무엇입니까? 요청에 사용자 정의 HTTP 헤더를 추가하거나 Http-Authorize를 사용합니까? –

+0

우수한 답변을 주셔서 감사합니다. –