Chcę uzyskać aktualnego użytkownika w celu uzyskania informacji o użytkowniku, takich jak e-mail. Ale nie mogę tego zrobić w asp.net core. Jestem taki zdezorientowany. To jest mój kod.
HttpContext
prawie ma wartość null w konstruktorze kontrolera. Nie jest dobrze przyciągać użytkownika do każdego działania. Chcę raz uzyskać informacje o użytkowniku i ustawić je w ViewData
;
public DashboardController()
{
var user = HttpContext.User.GetUserId();
}
c#
asp.net-core
asp.net-identity
Mehran Hafizi
źródło
źródło
Odpowiedzi:
EDYCJA dla konstruktora
Poniższy kod działa:
Edytuj dla RTM
Należy się zarejestrować
IHttpContextAccessor
:źródło
ClaimTypes.NameIdentifier
podaje aktualny identyfikator użytkownika iClaimTypes.Name
nazwę użytkownika.null
w moim przypadku? Ja.Net core 2.1 Web api
jednak używam .Prosty sposób to działa i sprawdziłem.
wtedy możesz wszystkie właściwości tych zmiennych, takie jak
user.Email
. Mam nadzieję, że to komuś pomoże.Edycja :
Jest to pozornie prosta, ale nieco skomplikowana przyczyna różnych typów systemów uwierzytelniania w ASP.NET Core. Aktualizuję, bo niektórzy dostają
null
.W przypadku uwierzytelniania JWT (testowane na ASP.NET Core v3.0.0-preview7): For JWT Authentication (Tested on ASP.NET Core v3.0.0-preview7):
źródło
Miej inny sposób na zdobycie bieżącego użytkownika w Asp.NET Core - i myślę, że widziałem to gdzieś tutaj, na SO ^^
Ten kod trafia do kontrolera o nazwie DemoController. Nie będzie działać bez obu await (nie będzie się kompilować);)
źródło
Muszę powiedzieć, że byłem dość zaskoczony, że HttpContext ma wartość null w konstruktorze. Jestem pewien, że to ze względu na wydajność. Potwierdziliśmy, że użycie w
IPrincipal
sposób opisany poniżej powoduje wstrzyknięcie go do konstruktora. Zasadniczo robi to samo, co zaakceptowana odpowiedź, ale w bardziej interfejsowy sposób.Dla każdego, kto szuka tego pytania i szuka odpowiedzi na ogólne pytanie „Jak zdobyć aktualnego użytkownika?” możesz uzyskać
User
bezpośredni dostęp zController.User
. Ale możesz to zrobić tylko wewnątrz metod akcji (zakładam, że kontrolery działają nie tylko z HttpContexts i ze względu na wydajność).Jeśli jednak potrzebujesz tego w konstruktorze (tak jak zrobił to OP) lub potrzebujesz stworzyć inne obiekty do wstrzyknięcia, które wymagają bieżącego użytkownika, poniższe jest lepszym podejściem:
Wstrzyknij IPrincipal, aby pobrać użytkownika
Najpierw spotkaj się
IPrincipal
iIIdentity
IPrincipal
iIIdentity
reprezentuje użytkownika i nazwę użytkownika. Wikipedia pocieszy Cię, jeśli hasło „Principal” brzmi dziwnie .Ważne jest, aby uświadomić sobie, że to, czy je dostać od
IHttpContextAccessor.HttpContext.User
,ControllerBase.User
czyControllerBase.HttpContext.User
jesteś coraz obiekt, który jest gwarantowany byćClaimsPrincipal
obiekt, który implementujeIPrincipal
.W tej chwili nie ma innego typu użytkownika, którego ASP.NET używa
User
(ale to nie znaczy, że inny nie mógłby zaimplementować czegoś innegoIPrincipal
).Więc jeśli masz coś, co ma zależność od `` aktualnej nazwy użytkownika '', którą chcesz wstrzyknąć, powinieneś wstrzykiwać,
IPrincipal
a na pewno nieIHttpContextAccessor
.Ważne: nie trać czasu na wstrzykiwanie
IPrincipal
bezpośrednio do kontrolera lub metody akcji - jest to bezcelowe, ponieważUser
jest już tam dostępne.W
startup.cs
:Następnie w twoim obiekcie DI, który potrzebuje użytkownika, którego po prostu wstrzykujesz,
IPrincipal
aby pobrać bieżącego użytkownika.Najważniejsze jest to, że jeśli robisz testy jednostkowe, nie musisz wysyłać
HttpContext
, a jedynie kpić z czegoś,IPrincipal
co reprezentuje to, co może byćClaimsPrincipal
.Jedna bardzo ważna rzecz, której nie jestem pewien w 100%. Jeśli chcesz uzyskać dostęp do rzeczywistych roszczeń
ClaimsPrincipal
, musisz przesłaćIPrincipal
doClaimsPrincipal
. To jest w porządku, ponieważ wiemy w 100%, że w czasie wykonywania jest tego typu (ponieważ takHttpContext.User
jest). Właściwie lubię to po prostu robić w konstruktorze, ponieważ już wiem na pewno, że każdyIPrincipal
będzieClaimsPrincipal
.Jeśli robisz kpiny, po prostu utwórz
ClaimsPrincipal
bezpośrednio i przekaż to do dowolnego ujęciaIPrincipal
.Dokładnie dlaczego nie ma interfejsu, bo
IClaimsPrincipal
nie jestem pewien. Zakładam, że MS zdecydowało, żeClaimsPrincipal
to tylko wyspecjalizowana „kolekcja”, która nie gwarantuje interfejsu.źródło
null
za zastrzykIPrincipal
. Musiałem również dodać usługę przejściową jako…GetService<IHttpContextAccessor>()?.HttpContext.User…
(z?
), ponieważ w przeciwnym razie uległaby awarii (GetService zwrócił wartość null).services.AddTransient(provider => provider.GetService<IHttpContextAccessor>().HttpContext.User);
jak HttpContext.User jest ClaimsPrincipal.Wydawałoby się, że na dzień dzisiejszy (kwiecień 2017 r.) Działa:
Przynajmniej w ciągu
Controller
źródło
=>
operatora, nazywa się to „definicją ciała wyrażenia” i jest opisane w tej dokumentacji . Na wypadek gdyby przyszli ludzie tacy jak ja się zastanawiali.IIdentity
nastring
, jak również stwierdzono w górnym komentarzu. Edycja po prostu to naprawiła. Nie jestem też pewien, jak doszedłeś do takiego wniosku (zwłaszcza, że punkty "redaktora" są przyznawane tylko użytkownikom poniżej 2k reputacji).Być może nie widziałem odpowiedzi, ale tak to robię.
Musisz zmienić te wartości
Startup.cs -> ConfigureServices (...)
Kontroler MVC lub Web Api
Metoda kontrolera:
Wynik to nazwa użytkownika, np. = Domena \ nazwa użytkownika
źródło
Mój problem polegał na uzyskaniu dostępu do zalogowanego użytkownika jako obiektu w pliku cshtml. Biorąc pod uwagę, że chciałeś użytkownika w ViewData, takie podejście może być pomocne:
W pliku cshtml
źródło
Oprócz istniejących odpowiedzi chciałbym dodać, że możesz również mieć instancję klasy dostępną dla całej aplikacji, która przechowuje dane związane z użytkownikiem, takie jak
UserID
itp.Może się przydać do refaktoryzacji np. nie chcesz pobierać
UserID
w każdej akcji kontrolera i deklarować dodatkowyUserID
parametr w każdej metodzie związanej z warstwą usług.Zrobiłem badania i oto mój post .
Po prostu rozszerzasz swoją klasę, z której wywodzisz
DbContext
się, dodającUserId
właściwość (lub implementując niestandardowy plikSession
klasę która ma tę właściwość).Na poziomie filtra możesz pobrać instancję klasy i ustawić
UserId
wartość.Następnie, gdziekolwiek wstrzykniesz swoją instancję - będzie ona zawierała niezbędne dane (czas życia musi wynosić na żądanie , więc rejestrujesz ją za pomocą
AddScoped
metodą).Przykład pracy:
Aby uzyskać więcej informacji, zobacz moją odpowiedź .
źródło
Zabieranie
IdentityUser
też by działało. To jest bieżący obiekt użytkownika i można pobrać wszystkie wartości użytkownika.źródło
Jeśli używasz scafolded Identity i Asp.net Core 2.2+, możesz uzyskać dostęp do bieżącego użytkownika z widoku takiego:
https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity?view=aspnetcore-2.2&tabs=visual-studio
źródło
To stare pytanie, ale mój przypadek pokazuje, że mój przypadek nie był tutaj omawiany.
Najbardziej podoba mi się odpowiedź Simon_Weaver ( https://stackoverflow.com/a/54411397/2903893 ). Wyjaśnia szczegółowo, jak uzyskać nazwę użytkownika za pomocą IPrincipal i IIdentity. Ta odpowiedź jest absolutnie poprawna i polecam takie podejście. Jednak podczas debugowania napotkałem problem, gdy ASP.NET NIE może poprawnie wypełnić zasady usługi . (lub innymi słowy, IPrincipal.Identity.Name ma wartość null)
Jest oczywiste, że aby uzyskać nazwę użytkownika, framework MVC powinien skądś wziąć to. W świecie .NET ASP.NET lub ASP.NET Core korzysta z oprogramowania pośredniego Open ID Connect. W prostym scenariuszu aplikacje internetowe uwierzytelniają użytkownika w przeglądarce internetowej. W tym scenariuszu aplikacja internetowa kieruje przeglądarkę użytkownika w celu zalogowania się do usługi Azure AD. Usługa Azure AD zwraca odpowiedź logowania za pośrednictwem przeglądarki użytkownika, która zawiera oświadczenia dotyczące użytkownika w tokenie zabezpieczającym. Aby działało w kodzie aplikacji, musisz podać uprawnienia, do których logują się delegaci aplikacji sieci Web. Podczas wdrażania aplikacji internetowej w usłudze Azure typowym scenariuszem spełniającym te wymagania jest skonfigurowanie aplikacji internetowej: „App Services” -> YourApp -> blok „Authentication / Authorization” -> „App Service Authenticatio” = „On”https://github.com/Huachao/azure-content/blob/master/articles/app-service-api/app-service-api-authentication.md ). Wierzę (to jest moje wyuczone przypuszczenie), że pod maską tego procesu kreator dostosowuje „nadrzędną” konfigurację internetową tej aplikacji internetowej, dodając te same ustawienia, które pokazuję w kolejnych akapitach. Zasadniczo problem, dlaczego to podejście NIE działa w ASP.NET Core, polega na tym, że konfiguracja maszyny „nadrzędnej” jest ignorowana przez konfigurację webconfig. (nie jest to w 100% pewne, po prostu podaję najlepsze wyjaśnienie, jakie mam). Tak więc, aby wszystko działało, musisz ustawić to ręcznie w swojej aplikacji.
Oto artykuł wyjaśniający, jak wielokrotnie skonfigurować aplikację do korzystania z usługi Azure AD. https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/tree/aspnetcore2-2
Krok 1: Zarejestruj przykład w dzierżawie usługi Azure AD. (to oczywiste, nie chcę spędzać czasu na wyjaśnieniach).
Krok 2: W pliku appsettings.json: Zastąp wartość ClientID identyfikatorem aplikacji z aplikacji zarejestrowanej w portalu rejestracji aplikacji w kroku 1. Zastąp wartość TenantId typową
Krok 3: Otwórz plik Startup.cs i w metodzie ConfigureServices po wierszu zawierającym .AddAzureAD wstaw następujący kod, który umożliwia aplikacji logowanie użytkowników za pomocą punktu końcowego usługi Azure AD v2.0, czyli pracy i szkoły oraz Konta osobiste Microsoft.
Podsumowanie : Pokazałem jeszcze jeden możliwy problem, który może prowadzić do błędu, że jest wyjaśniony starter tematu. Przyczyną tego problemu jest brak konfiguracji usługi Azure AD (oprogramowanie pośredniczące Open ID). W celu rozwiązania tego problemu proponuję ręcznie ustawić „Uwierzytelnianie / Autoryzacja”. Dodano krótkie omówienie sposobu konfiguracji.
źródło
Większość odpowiedzi pokazuje, jak najlepiej radzić sobie
HttpContext
z dokumentacją, z którą również poszedłem.Chciałem wspomnieć, że podczas debugowania będziesz chciał sprawdzić ustawienia projektu, wartość domyślna to
Enable Anonymous Authentication = true
.źródło
Mam swoje rozwiązanie
źródło