保護返回 JSON 的 ASP.NET MVC 控制器操作
我有一個 MVC3 應用程序,並且我的控制器操作使用
$$ Authorize $$屬性。到目前為止,一切都很好,表單身份驗證效果很好。現在我想向我的應用程序添加一個 JSON API,以便非瀏覽器客戶端可以訪問一些操作。 我很難找出“正確”的設計。
每個使用者都有秘密的 API 密鑰。
使用者 ID 5 呼叫http://myapp.com/foocontroller/baraction/5?param1=value1¶m2=value2&secure_hash=someValue。在這裡,secure_hash 只是 param1 和 param2 的值的 SHA1 雜湊,附加了使用者的 API 密鑰
/foocontroller/baraction 將被裝飾
$$ CustomAuthorize $$. 這將是 AuthorizeAttribute 的一個實現,它將檢查請求是否以 JSON 形式傳入。如果是,它將檢查雜湊並查看是否匹配。否則,如果請求是 HTML,那麼我呼叫現有授權。 我完全不確定這是否可行。在查詢字元串中傳遞安全雜湊是否正常,還是應該將其作為 HTTP 標頭傳遞?使用 HTTP 基本身份驗證而不是使用 API 密鑰生成的雜湊會更好嗎?
歡迎任何使用 ASP.NET MVC 製作 Web API 的人提供提示!
我在請求正文中傳遞秘密 API 密鑰以及使用者名和密碼。一旦獲得授權,就會生成一個令牌,客戶端必須在 Authorization 標頭中傳遞它。這會在每次請求時在基本控制器中進行檢查。
- 客戶端呼叫返回身份驗證令牌的 myapp.com/authorize。
- 客戶端在本地儲存身份驗證令牌。
- 客戶端呼叫 myapp.com/anycontroller,並在 Authorization 標頭中使用 authtoken。
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; } }