保护返回JSON的ASP.NET MVC控制器操作

时间:2011-05-01 22:30:46

标签: asp.net json authentication asp.net-mvc-3

我有一个MVC3应用程序,我的控制器操作使用[Authorize]属性进行保护。到目前为止,这么好,表格auth工作得很好。现在我想向我的应用程序添加一个JSON API,以便非浏览器客户端可以访问某些操作。

我无法弄清楚'正确'的设计。

1)每个用户都有秘密API密钥。

2)用户ID 5呼叫http://myapp.com/foocontroller/baraction/5?param1=value1&param2=value2&secure_hash=someValue。这里,secure_hash只是param1的SHA1哈希值,而param2的值附加了用户的秘密API密钥

2)/ foocontroller / baraction将使用[CustomAuthorize]进行修饰。这将是AuthorizeAttribute的一个实现,它将检查请求是否以JSON形式进入。如果是,它将检查散列并查看它是否匹配。否则,如果请求是HTML,那么我将调用现有授权。

我不确定这是否有效。在查询字符串中传递安全哈希是否正常,或者我应该将其作为HTTP头传递?使用HTTP基本身份验证而不是使用秘密API密钥创建的哈希是否更好?

欢迎任何使用ASP.NET MVC制作Web API的人提示!

1 个答案:

答案 0 :(得分:11)

我在请求正文中传递了秘密API密钥以及用户名和密码。授权后,将生成令牌,客户端必须在Authorization标头中传递该令牌。这会在每个请求中在基本控制器中进行检查。

  1. 客户端调用myapp.com/authorize,返回auth令牌。
  2. 客户端在本地存储身份验证令牌。
  3. 客户使用授权标题中的authtoken调用myapp.com/anycontroller。
  4. 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;
                }
            }
    
相关问题