Pobierz bieżącego użytkownika w ramach akcji ApiController, bez przekazywania identyfikatora użytkownika jako parametru

97

Jak uzyskać aktualnego użytkownika w bezpiecznej akcji ApiController, bez przekazywania userName lub userId jako parametru?

Zakładamy, że jest to możliwe, ponieważ jesteśmy w ramach bezpiecznej akcji. Bycie w bezpiecznej akcji oznacza, że ​​użytkownik został już uwierzytelniony, a żądanie ma jego token okaziciela. Biorąc pod uwagę, że WebApi autoryzowało użytkownika, może istnieć wbudowany sposób dostępu do userId bez konieczności przekazywania go jako parametru akcji.

Shaun Luttin
źródło
Zobacz tę odpowiedź: stackoverflow.com/a/26453782/3290276 Dodaj roszczenie
Gabriela Macias

Odpowiedzi:

149

W WebApi 2 można używać RequestContext.Principalz metody na ApiController

Darrel Miller
źródło
1
Wygląda na to, że nie mamy tej własności. Hmm. Może używamy starej wersji WebApi.
Shaun Luttin,
2
@ShaunLuttin Ok, więc jeśli używasz Web API 1, to uważam, że w ApiController istnieje właściwość Prinicpal. To tylko fantazyjne opakowanie wokół dostępu do kolekcji Request.Properties. Główny obiekt jest przechowywany w tym słowniku.
Darrel Miller,
6
Tylko nie zapomnijusing Microsoft.AspNet.Identity;
Overlord
1
@DarrelMiller to sposób na uzyskanie tego samego (powiedzmy kontekstu żądania) z innych części kodu (nie w kontrolerze).
Ajay Aradhya
2
@AjayAradhya Tylko jeśli to tam przekażesz. Wcześniejsze wysiłki na platformach internetowych pokazały, że używanie statycznych właściwości do dostępu do kontekstu żądania powoduje różnego rodzaju problemy architektoniczne. Na początku jest to wygodne, ale powoduje bardzo silny ból w dłuższej perspektywie.
Darrel Miller
36

Możesz również uzyskać dostęp do nazwy głównej za pomocą Userwłaściwości w ApiController.

Zatem poniższe dwa stwierdzenia są zasadniczo takie same:

string id;
id = User.Identity.GetUserId();
id = RequestContext.Principal.Identity.GetUserId();
Patrick
źródło
15
Próbuję użyć tego, co tu napisałeś, ale funkcja GetUserId () zawsze zwraca wartość null. Użytkownik jest autoryzowany, przekazuję token okaziciela, a ApiController ma nagłówek [Authorize]
Joshua Ohana
Funkcja GetUserId () zwraca identyfikator tylko wtedy, gdy użytkownik ma żądanie NameIdentifier. Aby zapoznać się z przykładem, jak rozwiązać ten problem, zapoznaj się z odpowiedzią Oswaldo tutaj: stackoverflow.com/questions/19505526
jramm
14

Wskazówka leży w automatycznie generowanym kontrolerze konta Webapi2

Miej tę właściwość z getter zdefiniowanym jako

public string UserIdentity
        {
            get
            {
                var user = UserManager.FindByName(User.Identity.Name);
                return user;//user.Email
            }
        }

i aby uzyskać UserManager - w WebApi2 - wykonaj jako Romans (czyt. jako AccountController)

public ApplicationUserManager UserManager
        {
            get { return HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>(); }
        }

Powinno to być zgodne z usługami IIS i trybem samodzielnego hosta

Karan Bhandari
źródło
7

Żadna z powyższych sugestii nie zadziałała dla mnie. Następujące zrobiły!

HttpContext.Current.Request.LogonUserIdentity.Name

Myślę, że istnieje wiele różnych scenariuszy i ten zadziałał dla mnie. Mój scenariusz obejmował frontend AngularJS i aplikację zaplecza Web API 2, oba działające pod kontrolą IIS. Musiałem ustawić obie aplikacje tak, aby działały wyłącznie z uwierzytelnianiem systemu Windows.

Nie ma potrzeby przekazywania żadnych informacji o użytkowniku. Przeglądarka i usługi IIS wymieniają poświadczenia zalogowanego użytkownika, a interfejs API sieci Web ma dostęp do poświadczeń użytkownika na żądanie (zakładam, że z usług IIS).

kannankeril
źródło
6

Odpowiedź Karan Bhandari jest dobra, ale AccountController dodany w projekcie to najprawdopodobniej plik Mvc.Controller. Aby przekonwertować jego odpowiedź do użycia w ApiController, zmień HttpContext.Current.GetOwinContext()na Request.GetOwinContext()i upewnij się, że dodano następujące 2 usinginstrukcje:

using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
Jeff Leach
źródło
5

W .Net Core użyj, User.Identity.Nameaby uzyskać nazwę użytkownika.

Venkatesh Muniyandi
źródło
2
User.Identity.Namepobiera wartość roszczenia nazwy . To nie jest specyficzne dla Active Directory.
Nate Barbettini
@Nate Dzięki za komentarz, naprawiłem to
Venkatesh Muniyandi
3

Jeśli używasz Asp.Identity UseManager, automatycznie ustawia wartość

RequestContext.Principal.Identity.GetUserId ()

na podstawie IdentityUser, którego używasz podczas tworzenia IdentityDbContext .

Jeśli kiedykolwiek implementujesz niestandardową tabelę użytkowników i uwierzytelnianie na okaziciela tokena, sprawdź moją odpowiedź.

Jak uzyskać kontekst użytkownika podczas wywołań Web Api?

Mam nadzieję, że to nadal pomaga. :)

pampi
źródło
1
string userName;
string userId;
if (HttpContext.Current != null && HttpContext.Current.User != null 
        && HttpContext.Current.User.Identity.Name != null)
{
    userName = HttpContext.Current.User.Identity.Name;
    userId = HttpContext.Current.User.Identity.GetUserId();
}

Lub w oparciu o komentarz Darrela Millera, może najpierw użyj tego do pobrania HttpContext.

// get httpContext
object httpContext;
actionContext.Request.Properties.TryGetValue("MS_HttpContext", out httpContext);    

Zobacz też:

Jak uzyskać dostęp do HTTPContext z poziomu akcji interfejsu API sieci Web

Shaun Luttin
źródło
5
Nie używaj HttpContext, ponieważ ogranicza to opcje hostingu i utrudnia testowanie kodu.
Darrel Miller,
Obiekt HttpContext nie będzie w słowniku, jeśli jesteś hostem własnym lub hostowanym przez OwinHttpListener
Darrel Miller,