如何通过Attribute(AuthorizeAttribute)为ApiController方法提供其他数据

时间:2014-01-08 23:24:59

标签: c# asp.net-mvc asp.net-web-api

我们的Web API将要求API的使用者提供我们分配给他们的API密钥。 API密钥将用于授权,并将用于添加数据(某处,某种程度上),以便ApiController的方法可以访问它们。

我正在考虑创建一个

的AuthorizationAttribute
  • 检查API密钥是否存在
  • 验证提供的API密钥是否对传入请求(引用者)有效
  • 如果API密钥存在且有效,它将用于获取ClientId和ClientName等数据,并将其添加到传入的Request的Properties集合中,以供ApiController中的方法使用。我们可能会将ClientId等编码为API密钥,并在服务器端对其进行解码或从数据库中检索它。

在我的dummied-up自定义AuthorizationAttribute中,如果授权成功,我通过执行以下操作将clientId和clientName添加到当前请求中:

actionContext.Request.Properties.add("clientId", 1234);
actionContext.Request.Properties.add("clientName", "Super Client");

然后在ApiController的一个方法中,我使用:

获取数据
int clientId = (int)Request.Properties["clientId"];
string clientName = (string)Request.Properties["clientName"];

这有效,但它假设{client}中存在“clientId”和“clientName”。我们可以使用Request.Properties进行检查,但我不想在Web API的每个方法中重复此检查代码。我想我可以有另一个属性进行检查,如果它无法在Request.Properties.ContainsKey中找到它们,则返回500内部服务器错误(错误请求400?)。

或者我们可以让AuthorizationAttribute执行授权,然后在每个ApiController方法中进行一次调用 - 返回一个Client对象,其中包含在JSON有效负载中提供的API密钥所需的数据。此时我们知道API密钥有效,因此我们将获得控制器处理请求所需的数据。

我们的ApiController方法将数据添加到Request for access的推荐方法是什么?所需的数据,但基于提供的有效API密钥(我们将从数据库中获取数据,或者将其编码到公共API密钥中并在我们的服务器上解码)。那会:

  • 最好不要违反DRY(检查已经添加了ApiController所需的数据,并且它们各自的值是正确的类型)
  • 确保值存在且方法可以执行而不会引发异常
  • 这应该分为两个属性吗?一个执行授权,下一个根据提供的API密钥获取所需的数据?

我们正在运行Visual Studio 2010,MVC 4,.NET 4.API密钥将作为JSON有效负载的一部分提供给Web API。

魔法弦将消失; - )

2 个答案:

答案 0 :(得分:0)

一种方法是为您的客户端提供公共共享密钥和私钥。对于每个发出的请求,客户端都需要将其公钥作为参数包括到期日期。到期日期的原因是,对其授权令牌有贡献的值将根据请求而变化。由于客户端将知道他们试图访问的资源并使其公钥有用,因此他们只需要确保他们发送的到期日期在服务器认为时间在utc内的容差阈值内。服务器和客户端都可以使用这些值及其假定的私钥创建安全哈希。然后,您可以验证发出请求的客户端>公钥是否是他们通过使用其私钥解密邮件的人。

每个传入消息都需要签名。如果在查询字符串上理论上它看起来像这样的注释:你也可以使用http标题:

Signature=<UrlEncode(Base64(HMAC-MD5(LowerCase( AbsolutePath(ResourceURL)) + UTCDate(ExpirationDate,“yyyyMMddHHmmss”)))> &Expires=<UTCDate(ExpirationDate ,“yyyyMMddHHmmss”)>&AccessKey=<PublicAccessKey>

对于您定义的每个需要授权的安全方法,如果哈希值有效,您可以让调用通过,否则返回未经授权的http状态代码。

答案 1 :(得分:0)

我建议使用MessageHandler,而不是使用ActionFilters。 MessageHandler可以查看请求,提取ClientId和ClientName(如果它们在那里)并将它们添加到属性中。然后在您需要提取该信息的控制器中,您可以使用ApiController扩展方法来访问controller.Request.Properties。这将封装你所有的魔法字符串。

我还建议将APIKey放在Authorization标头中,而不是放在JSON有效负载中,因为这正是Authorization标头的设计目的。