【问题标题】:WebAPI - How to get UserID from tokenWebAPI - 如何从令牌中获取用户 ID
【发布时间】:2016-06-21 08:32:09
【问题描述】:

我有 WebApi 应用程序并在 ApplicationOAuthProvider 类中将 UserID 添加到令牌:

    public override Task TokenEndpoint(OAuthTokenEndpointContext context)
    {
        foreach (KeyValuePair<string, string> property in context.Properties.Dictionary)
        {
            context.AdditionalResponseParameters.Add(property.Key, property.Value);
        }

        context.AdditionalResponseParameters.Add("ID", context.Identity.GetUserId<int>());

        return Task.FromResult<object>(null);
    }

现在如何在我的控制器方法中获取此 ID?

我尝试以下方法:

[Authorize]
public class ApiEditorialController : ApiController
{

    public HttpResponseMessage GetEditorialRequests()
    {
        int id = HttpContext.Current.User.Identity.GetUserId<int>();

        var r = Request.CreateResponse(HttpStatusCode.Accepted);
        r.ReasonPhrase = "Cool!";
        return r;
    }

}

但我在

上得到 NullReferenceException
int id = HttpContext.Current.User.Identity.GetUserId<int>(); 

字符串....

更新: 看看下面的响应(来自 Francis Ducharme)只是覆盖 OnAuthorization 而不是创建私有构造函数:)

public class AuthorizeApiFilter : AuthorizeAttribute
{
    public override void OnAuthorization(HttpActionContext actionContext)
    {
        string token = string.Empty;
        AuthenticationTicket ticket;

        token = (actionContext.Request.Headers.Any(x => x.Key == "Authorization")) ? actionContext.Request.Headers.Where(x => x.Key == "Authorization").FirstOrDefault().Value.SingleOrDefault().Replace("Bearer ", "") : "";

        if (token == string.Empty)
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized, "Missing 'Authorization' header. Access denied.");
            return;
        }

        //your OAuth startup class may be called something else...
        ticket = Startup.OAuthOptions.AccessTokenFormat.Unprotect(token);

        if (ticket == null)
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.BadRequest, "Invalid token decrypted.");
            return;
        }

        // you could perform some logic on the ticket here...

        // you will be able to retrieve the ticket in all controllers by querying properties and looking for "Ticket"... 
        actionContext.Request.Properties.Add(new KeyValuePair<string, object>("Ticket", ticket));
        base.OnAuthorization(actionContext);
    }
}

谢谢你,弗朗西斯·杜查姆

【问题讨论】:

  • 很奇怪,我今天给项目打了电话,它成功了……

标签: c# asp.net-web-api asp.net-web-api2 token access-token


【解决方案1】:

您可以在 OAuth 启动类的 GrantResourceOwnerCredentials 中将其添加到字典中。

ticket.Properties.Dictionary.Add(KeyValuePair<string, string>("UserID", user.Id.ToString())); //the user object from your authentication logic...

然后实现一个AuthorizeAttribute,您可以在其中检索在请求的Authorize 标头中发送的令牌,取消保护并将其添加到请求属性中,然后在所有控制器的方法中都可用。

public class AuthFilter : AuthorizeAttribute
{
    private void AuthorizeRequest(HttpActionContext actionContext)
    {
        string token = string.Empty;
        AuthenticationTicket ticket;

        token = (actionContext.Request.Headers.Any(x => x.Key == "Authorization")) ? actionContext.Request.Headers.Where(x => x.Key == "Authorization").FirstOrDefault().Value.SingleOrDefault().Replace("Bearer ", "") : "";

        if (token == string.Empty)
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized, "Missing 'Authorization' header. Access denied.");
            return;
        }

        //your OAuth startup class may be called something else...
        ticket = Startup.OAuthBearerOptions.AccessTokenFormat.Unprotect(token);

        if (ticket == null)
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.BadRequest, "Invalid token decrypted.");
            return;
        }

        // you could perform some logic on the ticket here...

        // you will be able to retrieve the ticket in all controllers by querying properties and looking for "Ticket"... 
        actionContext.Request.Properties.Add(new KeyValuePair<string, object>("Ticket", ticket));
    }
}

然后在您的网络方法中,Request.Properties 将包含Ticket,它本身有一个带有UserID 的字典。

您需要在WebApiConfig.cs中注册AuthorizeAttribute

config.Filters.Add(new AuthFilter());
// I also have this in my Web API config. Not sure if I had to add this manually or the default project had these lines already...
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));

【讨论】:

  • 我得到 mscorlib.dll 中出现“System.Collections.Generic.KeyNotFoundException”类型的异常,但未在用户代码中处理附加信息:字典中不存在给定的键。当我尝试拨打var ticket = Request.Properties["Ticket"];
  • 很奇怪,AuthFilter的代码从来没有被调用过,虽然我已经在WebApiConfig.cs中注册了...
  • 相同 :( AuthFilter.AuthorizeRequest 永远不会被调用
  • @OlegSh 既然我让你在全局范围内注册它,请尝试在你的网络方法上删除[Authorize] 属性。
  • 我当然删除了。 PS。很奇怪,但标准 userID = HttpContext.Current.User.Identity.GetUserId&lt;int&gt;(); 现在可以使用
【解决方案2】:

您需要拦截响应消息并将该值附加回您的用户。

AdditionalResponseParameters 将显示在响应中,但您的应用程序不会将它们分配给任何东西,除非您告诉它。

找到用于将声明值/名称等分配给用户的代码(在从 OAuth 提供程序重定向回您的站点时),然后在响应中查找参数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-05
    • 2021-07-05
    • 2013-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-04
    • 2012-08-13
    相关资源
    最近更新 更多