2016-03-07 1 views
3

У меня есть приложение WebAPI и добавил Идентификатор_пользователь лексемы в классе ApplicationOAuthProvider:WebAPI - Как получить 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); 
    } 

Теперь, как я могу получить этот идентификатор в моем методе контроллера?

Стараюсь следующее:

[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>(); 

строки ....

UPDATE: Посмотрите на ответ ниже (от Francis Ducharme) просто переопределяет OnAuthorization вместо этого, чтобы создать частный contructor :)

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

Спасибо, Фрэнсис Дюшарма

+0

очень странно, я назвал этот проект сегодня, и это работает ... –

ответ

2

Вы можете в GrantResourceOwnerCredentials вашего класса запуска OAuth добавить его туда в словарь.

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.

Вы должны зарегистрировать AuthorizeAttribute в WebApiConfig.cs

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)); 
+0

я получаю исключение типа «System.Collections.Generic.KeyNotFoundException» произошло в mscorlib.dll, но не обрабатывался в коде пользователя Дополнительная информация: Данный ключ не был указан в словаре. когда я пытаюсь вызвать 'var ticket = Request.Properties [" Ticket "];' –

+0

очень странно, код AuthFilter никогда не вызывается, хотя я зарегистрировал его в WebApiConfig.cs ... –

+0

Проверьте мое редактирование, возможно, Это исправить. –

0

Вам необходимо перехватить ответное сообщение и прикрепить это значение обратно к пользователю.

Параметр AdditionalResponseParameters будет отображаться в ответе, но ваше приложение не будет присваивать им что-либо, если вы не сообщите об этом.

Укажите код, который вы используете для присвоения имен/имен и т. Д. Вашим пользователям (при перенаправлении обратно на ваш сайт у поставщика OAuth), а затем найдите параметр в ответах.