web-dev-qa-db-fra.com

Mise en cache des revendications côté serveur avec l'authentification Owin

J'ai une application qui utilisait FormsAuthentication, et il y a quelque temps, je l'ai commutée pour utiliser IdentityModel de WindowsIdentityFramework afin de pouvoir bénéficier d'une authentification basée sur les revendications, mais elle était plutôt moche à utiliser et à mettre en œuvre. Alors maintenant, je regarde OwinAuthentication.

Je regarde OwinAuthentication et le cadre Asp.Net Identity. Mais la seule implémentation du framework Asp.Net Identity Pour le moment utilise EntityModel et j'utilise nHibernate. Pour l'instant, je cherche à contourner Asp.Net Identity Et à utiliser directement Owin Authentication. J'ai finalement pu obtenir une connexion de travail en utilisant les conseils de " Comment puis-je ignorer la magie d'Identity Framework et simplement utiliser le middleware d'authentification OWIN pour obtenir les revendications que je recherche? ", mais maintenant mon cookie contient les revendications sont assez importantes. Lorsque j'ai utilisé le IdentityModel, j'ai pu utiliser un mécanisme de mise en cache côté serveur qui a mis en cache les revendications sur le serveur et le cookie contenait simplement un jeton simple pour les informations mises en cache. Y a-t-il une fonctionnalité similaire dans OwinAuthentication, ou devrais-je l'implémenter moi-même?

Je pense que je vais être dans l'un de ces bateaux ...

  1. Le cookie reste à 3 Ko, eh bien c'est un peu gros.
  2. Activez une fonctionnalité similaire à SessionCaching de IdentityModel dans Owin que je ne connais pas.
  3. Écrivez ma propre implémentation pour mettre en cache les informations provoquant le gonflement du cookie et voir si je peux le connecter lorsque je configure Owin au démarrage de l'application.
  4. Je fais tout cela mal et il y a une approche à laquelle je n'ai pas pensé ou j'utilise mal quelque chose dans Owin.

    public class OwinConfiguration
    {
        public void Configuration(IAppBuilder app)
        {
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = "Application",
                AuthenticationMode = AuthenticationMode.Active,
                CookieHttpOnly = true,
                CookieName = "Application",
                ExpireTimeSpan = TimeSpan.FromMinutes(30),
                LoginPath = "/Login",
                LogoutPath = "/Logout",
                ReturnUrlParameter="ReturnUrl",
                SlidingExpiration = true,
                Provider = new CookieAuthenticationProvider()
                {
                    OnValidateIdentity = async context =>
                    {
                        //handle custom caching here??
                    }
                }
                //CookieName = CookieAuthenticationDefaults.CookiePrefix + ExternalAuthentication.ExternalCookieName,
                //ExpireTimeSpan = TimeSpan.FromMinutes(5),
            });
        }
    }
    

[~ # ~] mise à jour [~ # ~] J'ai pu obtenir l'effet souhaité en utilisant les informations fournies par Hongye et j'ai trouvé la logique ci-dessous ...

Provider = new CookieAuthenticationProvider()
{
    OnValidateIdentity = async context =>
    {
        var userId = context.Identity.GetUserId(); //Just a simple extension method to get the ID using identity.FindFirst(x => x.Type == ClaimTypes.NameIdentifier) and account for possible NULLs
        if (userId == null) return;
        var cacheKey = "MyApplication_Claim_Roles_" + userId.ToString();
        var cachedClaims = System.Web.HttpContext.Current.Cache[cacheKey] as IEnumerable<Claim>;
        if (cachedClaims == null)
        {
            var securityService = DependencyResolver.Current.GetService<ISecurityService>(); //My own service to get the user's roles from the database
            cachedClaims = securityService.GetRoles(context.Identity.Name).Select(role => new Claim(ClaimTypes.Role, role.RoleName));
            System.Web.HttpContext.Current.Cache[cacheKey] = cachedClaims;
        }
        context.Identity.AddClaims(cachedClaims);
    }
}
32
Nick Albrecht

Le middleware d'authentification de cookie OWIN ne prend pas encore en charge la fonctionnalité de mise en cache de session. # 2 n'est pas une option.

# 3 est la bonne voie à suivre. Comme Prabu l'a suggéré, vous devriez faire ce qui suit dans votre code:

OnResponseSignIn:

  • Enregistrer le contexte Identité dans le cache avec une clé unique (GUID)
  • Créer une nouvelle ClaimsIdentity intégrée avec la clé unique
  • Remplacez context.Identity par la nouvelle identité

OnValidateIdentity:

  • Obtenez la revendication de clé unique à partir du contexte.
  • Obtenez l'identité mise en cache par la clé unique
  • Appeler context.ReplaceIdentity avec l'identité mise en cache

J'allais vous suggérer de compresser le cookie, mais j'ai trouvé que OWIN l'avait déjà fait dans son TicketSerializer. Pas une option pour vous.

15
Hongye Sun
Provider = new CookieAuthenticationProvider()
{
    OnResponseSignIn = async context =>
    {
        // This is the last chance before the ClaimsIdentity get serialized into a cookie. 
        // You can modify the ClaimsIdentity here and create the mapping here. 
        // This event is invoked one time on sign in. 
    }, 
    OnValidateIdentity = async context => 
    {
        // This method gets invoked for every request after the cookie is converted 
        // into a ClaimsIdentity. Here you can look up your claims from the mapping table. 
    }
}
8
Praburaj

Vous pouvez implémenter IAuthenticationSessionStore pour stocker les cookies dans la base de données.

Voici un exemple de stockage de cookie dans redis.

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
SessionStore = new RedisSessionStore(new TicketDataFormat(dataProtector)),
LoginPath = new PathString("/Auth/LogOn"),
LogoutPath = new PathString("/Auth/LogOut"),

});

Consultez l'exemple complet ici

1
Alex Nguyen