Je dois faire quelque chose d'assez simple: dans mon application ASP.NET MVC, je veux définir un IIdentity / IPrincipal personnalisé. Selon ce qui est plus facile / plus approprié. Je souhaite étendre la valeur par défaut afin de pouvoir appeler quelque chose comme User.Identity.Id
et User.Identity.Role
. Rien d'extraordinaire, juste quelques propriétés supplémentaires.
J'ai lu des tonnes d'articles et de questions, mais j'ai l'impression de rendre les choses plus difficiles qu'elles ne le sont en réalité. Je pensais que ce serait facile. Si un utilisateur se connecte, je souhaite définir une IIdentité personnalisée. J'ai donc pensé, je vais implémenter Application_PostAuthenticateRequest
dans mon global.asax. Cependant, cela est appelé à chaque demande, et je ne veux pas appeler la base de données à chaque demande qui demanderait toutes les données de la base de données et mettrait un objet IPrincipal personnalisé. Cela semble également très inutile, lent et au mauvais endroit (faire des appels de base de données là-bas) mais je peux me tromper. Ou d'où proviendraient ces données?
J'ai donc pensé que chaque fois qu'un utilisateur se connecte, je peux ajouter des variables nécessaires dans ma session, que j'ajoute à la IIdentity personnalisée dans le Application_PostAuthenticateRequest
gestionnaire d'événements. Cependant, mon Context.Session
est null
là, donc ce n'est pas non plus la voie à suivre.
Je travaille là-dessus depuis un jour maintenant et je sens que je manque quelque chose. Cela ne devrait pas être trop difficile à faire, non? Je suis également un peu dérouté par toutes les choses (semi) liées à cela. MembershipProvider
, MembershipUser
, RoleProvider
, ProfileProvider
, IPrincipal
, IIdentity
, FormsAuthentication
.... Suis - je le seul qui trouve tout cela très confus?
Si quelqu'un pouvait me dire une solution simple, élégante et efficace pour stocker des données supplémentaires sur une IIdentity sans tout le fuzz supplémentaire .. ce serait génial! Je sais qu'il y a des questions similaires sur SO mais si la réponse dont j'ai besoin est là-dedans, j'ai dû l'oublier.
MemberShip...
,Principal
,Identity
. ASP.NET devrait rendre cela plus facile, plus simple et au plus deux approches pour gérer l'authentification.Réponses:
Voici comment je le fais.
J'ai décidé d'utiliser IPrincipal au lieu de IIdentity car cela signifie que je n'ai pas à implémenter à la fois IIdentity et IPrincipal.
Créer l'interface
CustomPrincipal
CustomPrincipalSerializeModel - pour sérialiser des informations personnalisées dans le champ de données utilisateur dans l'objet FormsAuthenticationTicket.
Méthode de connexion - configuration d'un cookie avec des informations personnalisées
Global.asax.cs - Lecture du cookie et remplacement de l'objet HttpContext.User, cela se fait en remplaçant PostAuthenticateRequest
Accès dans les vues Razor
et en code:
Je pense que le code est explicite. Si ce n'est pas le cas, faites-le moi savoir.
De plus, pour rendre l'accès encore plus facile, vous pouvez créer un contrôleur de base et remplacer l'objet utilisateur renvoyé (HttpContext.User):
puis, pour chaque contrôleur:
qui vous permettra d'accéder à des champs personnalisés en code comme celui-ci:
Mais cela ne fonctionnera pas dans les vues. Pour cela, vous devez créer une implémentation WebViewPage personnalisée:
Faites-en un type de page par défaut dans Views / web.config:
et dans les vues, vous pouvez y accéder comme ceci:
la source
Thread.CurrentPrincipal
àApplication_PostAuthenticateRequest
pour que cela fonctionne car elle ne repose surHttpContext.Current.User
FormsAuthentication.SignOut();
fonctionne très bien pour moi.Je ne peux pas parler directement pour ASP.NET MVC, mais pour ASP.NET Web Forms, l'astuce consiste à créer un
FormsAuthenticationTicket
et à le chiffrer dans un cookie une fois que l'utilisateur a été authentifié. De cette façon, vous n'avez qu'à appeler la base de données une fois (ou AD ou tout ce que vous utilisez pour effectuer votre authentification), et chaque demande suivante s'authentifiera en fonction du ticket stocké dans le cookie.Un bon article à ce sujet:
http://www.ondotnet.com/pub/a/dotnet/2004/02/02/effectiveformsauth.html(lien brisé)Éditer:
Étant donné que le lien ci-dessus est rompu, je recommanderais la solution de LukeP dans sa réponse ci-dessus: https://stackoverflow.com/a/10524305 - Je suggérerais également que la réponse acceptée soit remplacée par celle-ci.
Edit 2: une alternative pour le lien brisé: https://web.archive.org/web/20120422011422/http://ondotnet.com/pub/a/dotnet/2004/02/02/effectiveformsauth.html
la source
Cache
commeSession
remplacement pour conserver les données sur le serveur. Quelqu'un peut-il me dire s'il s'agit d'une approche défectueuse?Voici un exemple pour faire le travail. bool isValid est défini en regardant une banque de données (disons votre base de données utilisateur). UserID est juste un ID que je conserve. Vous pouvez ajouter des informations supplémentaires telles que l'adresse e-mail aux données utilisateur.
dans le golbal asax ajoutez le code suivant pour retrouver vos informations
Lorsque vous allez utiliser les informations ultérieurement, vous pouvez accéder à votre principal personnalisé comme suit.
cela vous permettra d'accéder aux informations utilisateur personnalisées.
la source
MVC vous fournit la méthode OnAuthorize qui se bloque à partir de vos classes de contrôleur. Vous pouvez également utiliser un filtre d'action personnalisé pour effectuer l'autorisation. MVC le rend assez facile à faire. J'ai posté un blog à ce sujet ici. http://www.bradygaster.com/post/custom-authentication-with-mvc-3.0
la source
Voici une solution si vous devez connecter certaines méthodes à @User pour les utiliser dans vos vues. Aucune solution pour une personnalisation sérieuse de l'adhésion, mais si la question d'origine était nécessaire pour les seules vues, cela suffirait peut-être. Ce qui suit a été utilisé pour vérifier une variable renvoyée par un filtre d'autorisation, utilisé pour vérifier si certains liens devaient être présentés ou non (pas pour tout type de logique d'autorisation ou d'octroi d'accès).
Ensuite, ajoutez simplement une référence dans les zones web.config, et appelez-la comme ci-dessous dans la vue.
la source
Basé sur la réponse de LukeP , et ajoutez quelques méthodes de configuration
timeout
et derequireSSL
coopérationWeb.config
.Les liens de références
Codes modifiés de LukeP
1, ensemble
timeout
basé surWeb.Config
. Le FormsAuthentication.Timeout obtiendra la valeur de délai d' attente, qui est défini dans web.config. J'ai encapsulé les éléments suivants pour être une fonction, qui renvoie unticket
retour.2, configurez le cookie pour qu'il soit sécurisé ou non, en fonction de la
RequireSSL
configuration.la source
Très bien, donc je suis un chiffreur sérieux ici en faisant glisser cette très vieille question, mais il y a une approche beaucoup plus simple à cela, qui a été abordée par @Baserz ci-dessus. Et cela consiste à utiliser une combinaison de méthodes d'extension C # et de mise en cache (NE PAS utiliser de session).
En fait, Microsoft a déjà fourni un certain nombre de ces extensions dans l'
Microsoft.AspNet.Identity.IdentityExtensions
espace de noms. Par exemple,GetUserId()
est une méthode d'extension qui renvoie l'ID utilisateur. Il existe égalementGetUserName()
etFindFirstValue()
, qui renvoie des réclamations basées sur l'IPrincipal.Il vous suffit donc d'inclure l'espace de noms, puis d'appeler
User.Identity.GetUserName()
pour obtenir le nom des utilisateurs tel que configuré par ASP.NET Identity.Je ne suis pas certain si cela est mis en cache, car l'ancienne identité ASP.NET n'est pas open source, et je n'ai pas pris la peine de procéder à une rétro-ingénierie. Cependant, si ce n'est pas le cas, vous pouvez écrire votre propre méthode d'extension, qui mettra en cache ce résultat pendant une durée spécifique.
la source
IsUserAdministrator
ouUserEmail
etc.? Tu pensesHttpRuntime.Cache
?En plus du code LukeP pour les utilisateurs de Web Forms (pas MVC) si vous souhaitez simplifier l'accès dans le code derrière vos pages, ajoutez simplement le code ci-dessous à une page de base et dérivez la page de base dans toutes vos pages:
Ainsi, dans votre code derrière, vous pouvez simplement accéder à:
Ce qui me manque dans un scénario de formulaire Web, c'est comment obtenir le même comportement dans du code non lié à la page, par exemple dans httpmodules dois-je toujours ajouter un cast dans chaque classe ou existe-t-il un moyen plus intelligent pour l'obtenir?
Merci pour vos réponses et merci à LukeP que j'ai utilisé vos exemples comme base pour mon utilisateur personnalisée (qui a maintenant
User.Roles
,User.Tasks
,User.HasPath(int)
,User.Settings.Timeout
et bien d' autres choses belles)la source
J'ai essayé la solution suggérée par LukeP et j'ai constaté qu'elle ne prend pas en charge l'attribut Authorize. Donc, je l'ai un peu modifié.
Et enfin dans Global.asax.cs
Maintenant, je peux accéder aux données dans les vues et les contrôleurs simplement en appelant
Pour me déconnecter, j'appelle
où AuthManager est
la source