Доступ к QueryString в пользовательском атрибуте AuthorizeAttribute

Я использую 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!";
}

Как вы могли заметить, я не смог получить доступ к QueryString в любом месте из параметра HttpActionContext и должен был сам его создать. Похоже, они явно удалили QueryString из этого объекта Request. Я не хочу добавлять "токен" к каждому API-методу, чтобы получить его в данных маршрута.

Итак, мои вопросы:

  • Является ли QueryString там где-то, и я просто пропущу его? Если нет, любая идея, почему Microsoft не включает его с этим объектом Request? (может быть, это плохо?)
  • Есть ли лучший способ справиться с получением токена в AuthorizeAttribute (опять же, не добавляя его к каждому вызову)?

Кстати, я понимаю, что есть другие (вероятно, лучшие) варианты авторизации, такие как Basic Authentication и OAuth, и я не хочу обсуждать эту тему здесь.

Ответ 1

Несмотря на то, что ответ Адама Тала совершенно действителен, в новом мировом порядке Web API вы действительно не хотите использовать что-либо из System.Web имен System.Web; на самом деле вы даже не хотите ссылаться на это. Увы, вы можете получить доступ к строке запроса из метода расширения GetQueryNameValuePairs(). Это позволит вам ослабить привязку System.Web к лодке и все равно получить то, что вам нужно.

using System.Net.Http;

var queryString = actionContext.Request
        .GetQueryNameValuePairs()
        .ToDictionary(x => x.Key, x => x.Value);

Ответ 2

Try

using System.Web;

HttpContext.Current.Request.QueryString

Ответ 3

NameValueCollection queryString = actionContext.Request.RequestUri.ParseQueryString();

Это работает для меня.