2011-05-01 80 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簡單地是param1的SHA1哈希和param2的值,並且附加了用戶的祕密API密鑰。012)這將是一個AuthorizeAttribute的實現,它將檢查請求是否以JSON形式進入。如果是,它將檢查散列並查看它是否匹配。否則,如果請求是HTML,那麼我調用現有的授權。

我完全不知道這是否可行。在查詢字符串中傳遞安全哈希是正常的,還是應該將它作爲HTTP頭傳遞?使用HTTP基本身份驗證而不是使用祕密API密鑰創建的哈希更好嗎?

任何使用ASP.NET MVC製作Web API的人的建議都會受到歡迎!

回答

11

我在請求主體中傳遞了祕密API密鑰以及用戶名和密碼。一旦授權,就會生成一個令牌,並且客戶端必須將其傳遞給授權標頭。這將在每個請求的基礎控制器中進行檢查。

  1. 客戶端調用myapp.com/authorize返回auth令牌。
  2. 客戶端本地存儲auth令牌。
  3. 客戶端調用myapp.com/anycontroller,並在授權標頭中使用authtoken。

AuthorizeController來自控制器繼承。 Anycontroller繼承自執行授權代碼的自定義基礎控制器。

我的示例需要以下的路徑,其引導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的背景),所以我就如何授權屬性工作模糊。謝謝! – 2011-05-01 22:55:38

+0

謝謝傑森!你是如何「傳之祕API密鑰與請求主體的用戶名和密碼一起」?你只是添加自定義的HTTP頭到請求或者你使用Http-Authorize? – 2011-05-01 23:20:09

+0

非常好,謝謝你的詳細回覆! – 2011-05-02 04:17:16

相關問題