如何解决保护返回JSON的ASP.NET MVC控制器操作
|| 我有一个MVC3应用程序,并且我的控制器动作是使用[Authorize]属性保护的。到目前为止,形式验证非常好。现在,我想向应用程序中添加JSON API,以便非浏览器客户端可以访问某些操作。 我在弄清楚“正确”的设计时遇到了麻烦。 1)每个用户都有秘密的API密钥。 2)用户ID 5调用http://myapp.com/foocontroller/baraction/5?param1=value1¶m2=value2&secure_hash=someValue。在这里,secure_hash只是参数1和参数2的值的SHA1哈希值,并附加了用户的秘密API密钥 2)/ foocontroller / baraction将使用[CustomAuthorize]装饰。这将是AuthorizeAttribute的实现,它将检查请求是否作为JSON传入。如果是,它将检查哈希并查看是否匹配。否则,如果请求是HTML,则调用现有授权。 我完全不确定这是否行得通。在查询字符串中传递安全哈希是正常的还是应该将其作为HTTP标头传递?使用HTTP基本身份验证代替使用秘密API密钥创建的哈希值更好吗? 欢迎使用ASP.NET MVC制作过Web API的任何人的提示!解决方法
我在请求正文中传递了秘密API密钥以及用户名和密码。获得授权后,将生成令牌,客户端必须将其传递到Authorization标头中。在每个请求的基础控制器中都会对此进行检查。
客户端调用myapp.com/authorize,它返回身份验证令牌。
客户端将身份验证令牌存储在本地。
客户端使用授权头中的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;
}
}