在自定义AuthorizeAttribute中访问QueryString

Thi*_*Guy 12 c# asp.net-mvc asp.net-web-api

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

https://mysite.com/api/Ping?token=[issued-token]
Run Code Online (Sandbox Code Playgroud)

我有一个像这样的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");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我可以像这样装饰我的API.注意:这只是一个示例,真正的呼叫将从其帐户读取数据(帐户标识符在其令牌中加密)并返回它.

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

您可能会注意到,我无法从HttpActionContext参数访问QueryString,并且必须自己构建它.看起来他们从这个Request对象中明确地删除了QueryString.我不想将"令牌"添加到每个API方法中,以便在路由数据中获取它.

所以我的问题是:

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

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

Buv*_*uvy 31

虽然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);
Run Code Online (Sandbox Code Playgroud)

  • 只是添加(因为我花了一秒钟才找到它),你可以通过使用`System.Net.Http`命名空间找到这个扩展方法. (7认同)
  • 完全正确.特别是如果有人想要使用vnext并摆脱System.Web.你有我的upvote :) (3认同)

Ada*_*Tal 11

尝试

using System.Web;

HttpContext.Current.Request.QueryString
Run Code Online (Sandbox Code Playgroud)