Zadałeś dwa pytania (1) najlepsze miejsce do uzyskania informacji o użytkowniku i (2) jak je zapisać w sesji. Odpowiem (1) iw ten sposób być może pokażę, że nie musisz umieszczać żadnych dodatkowych informacji w sesji.
Poinformowałeś, że twoja aplikacja używa uwierzytelniania systemu Windows, więc oznacza to, że ciężka praca nad uwierzytelnieniem użytkownika została już wykonana przez IIS/HttpListener zanim aplikacja otrzyma żądanie. Po otrzymaniu żądania pojawi się WindowsPrincipal
w HttpContext.User
. Będzie to miało już nazwę użytkownika Windows i role AD już ustalone, ale chcesz użyć dodatkowych ról przechowywanych w bazie danych ...
Możesz uzyskać dostęp do swojej AuthService
z dowolnego miejsca w aplikacji, ale prawdopodobnie najlepszym sposobem jest zarejestrowanie IAuthorizationFilter
i wykonaj tam pracę. Postępując zgodnie z tym podejściem, dodatkowe role i inne informacje pobierane z bazy danych będą dostępne w metodach kontrolera i, co być może ważniejsze, z dodatkowego kodu biblioteki, który wymaga sprawdzenia poświadczeń użytkownika.
Przed .Net 4.5, jeśli chcesz dodać dodatkowe informacje do WindowsPrincipal
Myślę, że Twoim jedynym wyborem było zastąpienie dostarczonego przez system użytkownika innym obiektem, który zaimplementował interfejs IPrincipal
. To podejście jest nadal dostępne (i co polecam), ale od czasu wprowadzenia Windows Identity Foundation (WIF) w .Net 4.5, WindowsPrincipal
pochodzi z System.Security.Claims.ClaimsIdentityClaimsIdentity
, który obsługuje dodawanie dodatkowych ról (i innych użytecznych informacji) do głównego systemu podanego przez użytkownika. Jednak, jak zauważyło kilka osób, w systemie Windows występuje błąd/funkcja, która może powodować zgłaszanie wyjątku podczas sprawdzania ról, które zostały dodane programowo. Stwierdziliśmy, że prostym i niezawodnym sposobem uniknięcia tego jest zastąpienie Użytkownika numerem GenericPrincipal
.
wymaganych etapów:
(1) tworzą się IAuthorizationFilter
.
class MyAuthorizationFilter : IAuthorizationFilter
{
AuthService _authService;
public MyAuthorizationFilter(AuthService authService)
{
_authService = authService;
}
public void OnAuthorization(AuthorizationContext filterContext)
{
var principal = filterContext.HttpContext.User;
if (principal.Identity != null && principal.Identity.IsAuthenticated)
{
// Add username (and other details) to session if you have a need
filterContext.HttpContext.Session["User"] = principal.Identity.Name;
// get user info from DB and embue the identity with additional attributes
var user = _authService.GetUserInfo(principal.Identity.Name);
// Create a new Principal and add the roles belonging to the user
GenericPrincipal gp = new GenericPrincipal(principal.Identity, user.RoleNames.ToArray());
filterContext.HttpContext.User = gp;
}
}
}
(2) Zarejestruj swój filtr. Można to zarejestrować na poziomie kontrolera lub globalnie. Zazwyczaj można to zrobić w App_Start\FilterConfig.cs
:
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new MyAuthorizationFilter(new AuthService()));
}
}
(3) Za pomocą dostarczonego GenericPrincipal
w kodzie aplikacji, aby odpowiedzieć na pytania dotyczące identyfikacji użytkownika i innych danych uwierzytelniających. na przykład w swojej metodzie sterownika możesz uzyskać dostęp do nazwy użytkownika lub innych "roszczeń" (np. adresu e-mail) zapisanych w filtrze GenericPrincipal
przez filtr.
public ActionResult Index()
{
ViewBag.Name = HttpContext.User.Identity.Name;
if(HttpContext.User.IsInRole("Administrator"))
{
// some role-specific action
}
return View();
}
Ponieważ używałem wbudowanego mechanizmu nagrać Principal role, można uzyskać dostęp z dowolnego dane użytkownika za pomocą HttpContext.User
lub System.Threading.Thread.CurrentPrincipal
. Możesz także użyć metody kontrolera, aby zadeklarować, które akcje są dostępne dla określonych ról lub użytkowników. na przykład
public class HomeController : Controller
{
[Authorize(Roles = "Administrator")]
public ActionResult Admin()
{
return View();
}
Zobacz MSDN celu uzyskania dalszych informacji na temat ClaimsIdentity
Mam nadzieję, że to pomoże
-Rob
Rob Bardzo dziękuję za odpowiedź. Twoje rozwiązanie polegające na uzyskiwaniu ról jest niesamowite, ale bardzo potrzebuję uzyskać userid do sesji z powodów takich, jak pobranie pewnych informacji z bazy danych według userid itp. Czy mogę pomóc mi uzyskać userid do sesji? :-) Nie wiem, gdzie jest najlepsze miejsce do zrobienia? Dzięki. – Jenan
Cześć Jenan. Możesz dodać nazwę użytkownika do sesji w polu AuthorizationFilter, jeśli musisz (zaktualizowałem odpowiedź, aby to pokazać), ale nie jestem pewien, dlaczego musiałbyś to zrobić. Możesz uzyskać dostęp do Zleceniodawcy (i od niego Identity.Username) z dowolnego kodu za pomocą HttpConext.User (w swoim kontrolerze) lub, jeśli jesteś głębiej w bibliotece kodu, możesz użyć System.Threading.Thread.CurrentPrincipal. – Rob
Rob, dziękuję bardzo za poświęcony czas. Ta odpowiedź jest dla mnie wspaniała. – Jenan