13

我正在使用 Web API 并设置了一个简单的身份验证和授权机制,调用者在其中传递了我在查询字符串中颁发给他们的令牌。所以他们提交了如下请求:

https://mysite.com/api/Ping?token=[issued-token]

我有一个这样的 ApiAuthorizeAttribute:

public class ApiAuthorizeAttribute : System.Web.Http.AuthorizeAttribute
{
    public ApiPermission Permission { get; set; }

    public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        switch (Permission)
        {
            case ApiPermission.None: 
               return;

           case ApiPermission.Write:
           case ApiPermission.Read:

               string query = actionContext.Request.RequestUri.Query;
               var nvc = System.Web.HttpUtility.ParseQueryString(query);
               string token = nvc["token"];

               // (my code to map the token to an Authorization for the request)               
               ApiAuthorization auth = ApiToken.GetAuthorization(token);
               if (auth != null && auth.HasPermission(Permission))
                   return;

               HandleUnauthorizedRequest(actionContext);
               return;

           default:
               throw new ArgumentException("Unexpected Permission");
        }
    }
}

然后我可以像这样装饰我的 API。注意:这只是一个例子,真正的调用会从他们的账户中读取数据(账户标识符在他们的令牌中加密)并返回。

/// <summary>
/// Ping service that requires a Token with Read permission
/// Returns "Success!"
/// </summary>
[ApiAuthorize(Permission = ApiPermission.Read)]
[HttpGet]
public string Ping()
{
    return "Success!";
}

正如您可能注意到的,我无法从 HttpActionContext 参数的任何地方访问 QueryString 并且必须自己构建它。他们似乎从这个 Request 对象中明确删除了 QueryString 。我不想将它添加到每个 API 方法中,以便在路由数据中获取它。

所以我的问题是:

  1. QueryString 是否在某处而我只是想念它?如果没有,知道为什么微软不将它包含在这个 Request 对象中吗?(即,也许这是一件坏事?)
  2. 有没有更好的方法来处理在 AuthorizeAttribute 中获取令牌(同样,不将其添加到每个调用中)?

顺便说一句,我意识到还有其他(可能更好)的授权选项,例如基本身份验证和 OAuth,我不想在这里讨论这个话题。

4

3 回答 3

34

虽然 Adam Tal 的回答完全有效,但在 Web API 新世界秩序中,您真的不想使用System.Web命名空间中的任何东西;事实上,你甚至不想引用它。唉,您可以从 GetQueryNameValuePairs() 扩展方法获取查询字符串。这将让您切断 System.Web 船锚,但仍能满足您的需求。

using System.Net.Http;

var queryString = actionContext.Request
        .GetQueryNameValuePairs()
        .ToDictionary(x => x.Key, x => x.Value);
于 2014-09-11T21:10:04.037 回答
12

尝试

using System.Web;

HttpContext.Current.Request.QueryString
于 2013-05-29T05:16:31.980 回答
1
NameValueCollection queryString = actionContext.Request.RequestUri.ParseQueryString();

这个对我有用。

于 2019-09-25T10:39:15.293 回答