简体   繁体   English

WebAPI - 如何从令牌获取UserID

[英]WebAPI - How to get UserID from token

I have WebApi application and added UserID to token in ApplicationOAuthProvider class: 我有WebApi应用程序并将UserID添加到ApplicationOAuthProvider类中的标记:

    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);
    }

Now how can I get this ID in my controller method? 现在如何在我的控制器方法中获取此ID?

I try the following: 我尝试以下方法:

[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;
    }

}

But I get NullReferenceException on 但是我得到了NullReferenceException

int id = HttpContext.Current.User.Identity.GetUserId<int>(); 

string.... 串....

UPDATE: Look at the Response below (from Francis Ducharme) just override OnAuthorization instead on create private contructor :) 更新:看下面的响应(来自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);
    }
}

Thank you, Francis Ducharme 谢谢Francis Ducharme

You could, in GrantResourceOwnerCredentials of your OAuth startup class, add it there to the dictionary. 您可以在OAuth启动类的GrantResourceOwnerCredentials中将其添加到字典中。

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

Then Implement an AuthorizeAttribute in which you can retrieve the token that was sent in the Authorize header of the request, unprotect it and add it to the request properties that will then be available in all controllers' methods. 然后实现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));
    }
}

Then in your web methods, Request.Properties will contain Ticket , which itself has a dictionary with the UserID . 然后在您的Web方法中, Request.Properties将包含Ticket ,它本身具有带UserID的字典。

You need to register the AuthorizeAttribute in WebApiConfig.cs 您需要在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));

You need to intercept the response message and attach that value back to your user. 您需要拦截响应消息并将该值附加回您的用户。

The AdditionalResponseParameters will show up in the response, but your application won't assign them to anything unless you tell it to. AdditionalResponseParameters将显示在响应中,但除非您告诉它,否则您的应用程序不会将它们分配给任何内容。

Locate the code that you use to assign claim values / name etc to your users (on the redirect back to your site from the OAuth provider), and then look for the parameter on the respones there. 找到用于为用户分配声明值/名称等的代码(在从OAuth提供程序重定向回您的站点时),然后在响应中查找参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM