【问题标题】:Accessing QueryString in a custom AuthorizeAttribute在自定义 AuthorizeAttribute 中访问 QueryString
【发布时间】:2013-05-29 05:08:41
【问题描述】:

我正在使用 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 方法中,以便在 Route Data 中获取它。

所以我的问题是:

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

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

【问题讨论】:

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


【解决方案1】:

虽然 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);

【讨论】:

  • 只是添加(因为我花了一秒钟才找到它),您可以使用System.Net.Http命名空间找到这个扩展方法。
  • 完全正确。特别是如果有人想使用 vnext 并摆脱 System.Web。你得到了我的支持:)
【解决方案2】:

试试

using System.Web;

HttpContext.Current.Request.QueryString

【讨论】:

  • 是的,这行得通。对于如此直接的答案,这是一个相当冗长的问题......但我仍然想知道为什么它不在他们的 Request 对象中 - 它让我感觉也许我不应该抓住参数AuthorizeAttribute 中的查询字符串。
  • 关于如何访问帖子请求的任何想法
  • @jaminator - 尝试使用包含发布数据的 HttpContext.Current.Request.Form 字典,而不是从 url 获取数据的 QueryString。
  • @AdamTal 数据在 json post 请求中传递给我
  • @jaminator - 你试过我的建议了吗?
【解决方案3】:
NameValueCollection queryString = actionContext.Request.RequestUri.ParseQueryString();

它对我有用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-05
    • 2015-10-06
    相关资源
    最近更新 更多