Nous utilisons la sécurité du ressort dans notre application Web. La plupart des pages sont sécurisées, c'est-à-dire un utilisateur DOIT être connecté pour accéder à ces pages. Cela fonctionne bien généralement. Cependant, nous rencontrons un comportement indésirable lors de la déconnexion. P>
Supposons qu'un utilisateur soit connecté et envoie une demande auprès de la page de frappe pour charger une page (sécurisée). Avant que cette demande soit terminée, le même utilisateur envoie une demande de déconnexion (c'est-à-dire une demande avec servle_path "/ j_spring_security_logout"). La demande de déconnexion est généralement très rapide et elle peut être complétée plus tôt que la demande précédente. Bien sûr, la demande de déconnexion efface le contexte de sécurité. Par conséquent, la requête précédente perd le contexte de sécurité au milieu de sa vie et cela provoque généralement une exception. P>
En fait, l'utilisateur n'a pas besoin de démarrer la première demande "manuellement". Ce scénario peut arriver sur une page avec une actualisation automatique, c'est-à-dire que l'utilisateur appuie sur le lien de déconnexion, une fraction de seconde après une actualisation a été envoyée automatiquement. P>
d'un point de vue, cela peut être considéré comme un comportement significatif. D'autre part, je préférerais empêcher une telle perte de contexte de sécurité au milieu de la vie d'une demande. P>
Y a-t-il un moyen de configurer la sécurité du printemps pour éviter cela? (Quelque chose comme "Effacement du contexte de sécurité au cours de laquelle il existe d'autres demandes concurrentes de la même session" ou "lisez le contexte de sécurité une seule fois lors d'une seule demande et mettez-le en cache pour une utilisation supplémentaire") P>
merci. p>
3 Réponses :
Donc, c'est tout (sans surprise) par conception. Ces Sécurité du ressort Docs donne une bonne explication quant à ce qui se passe - citant:
Dans une application qui reçoit des demandes simultanées en une seule session, la même instance
SecurityContext code> sera partagée entre les threads. Même si un
threadlocal code> est utilisé, il s'agit de la même instance extraite du
httpsession code> pour chaque thread. Cela a des implications si vous souhaitez modifier temporairement le contexte sous lequel un thread est en cours d'exécution. Si vous utilisez simplement
SecurityContexTholder.getContext () CODE> et appelez
SETUuthentication (anauthentication) code> sur l'objet contextuel renvoyé, l'objet code> authentification code> changera Tous les threads simultanés qui partagent le même
SecurityContext Code> instance. Vous pouvez personnaliser le comportement de
SecurityContextPersSistenceFilter code> pour créer un tout nouveau
SecurityContext CODE> pour chaque demande, empêchant ainsi les modifications d'un thread de l'affectation d'une autre. Sinon, vous pouvez créer une nouvelle instance juste au point où vous modifiez temporairement le contexte. La méthode
SecurityContextholder.createempontextextextex () code> renvoie toujours une nouvelle instance de contexte. P> blockQuote>
Un extrait de la citation ci-dessus dit: P>
... Vous pouvez personnaliser le comportement de
SpringContextPersistenceFilter code> ... p> blockQuote>
Malheureusement, les DOC ne fournissent aucune information sur la manière de faire cela, ni comment il serait même approché. Ce Donc, question demande la chose même (essentiellement, est une version distillée de cette question), mais il n'a pas reçu beaucoup d'attention. P>
Il y a aussi ce Réponse qui fournit un peu plus de profondeur dans le fonctionnement interne de
httpsessionsecurityContextrepository code>, qui est susceptible d'être la pièce qui devrait être ré-écrite / Mis à jour afin de s'attaquer à ce problème. P>
Je mettrai à jour cette réponse si je viens de résoudre ce problème (comme la création d'une nouvelle instance du contexte) dans la mise en œuvre. P>
MISE À JOUR H2>
La racine du problème que je ressens était liée à la lecture d'un attribut d'identifiant de l'utilisateur hors du
httpsession code> (après avoir été effacé par une "déconnexion simultanée" " demander). Au lieu d'implémenter mon propre
SpringContextrepository Code> J'ai décidé de créer un filtre simple qui enregistre l'authentification code> actuelle code> à la demande, puis travaillez à partir de là. P>
Voici Le filtre de base: p>
xxx pré> qui doit être ajouté après le
SecurityContextPersSenseFilter code> En ajoutant ce qui suit à votre
WebSecurityConfigurierAdapter code>
Configurer (HTTPSececurity HTTP) CODE> Méthode. P>
http.addFilterAfter(new SaveAuthToRequestFilter(), SecurityContextPersistenceFilter.class)
Disclaimer: le comportement en question a été mis en œuvre à dessein. Et si quelqu'un décide de le désactiver, ils devraient lire SEC-2025 que décrit le problème que vous obtenez en retour.
b>
Si je comprends bien cela correctement, le problème est que la déconnexion efface les données authentification de SecurityContext de SecurityContext CODE> rendant ainsi P>
private boolean clearAuthentication = true;
Je pense que la question dans sec-2025 code> ne doit pas être prise légèrement. Voir la FIX COMMIT qui illustre succinctement le problème: Github.com/spring-Projects/ Spring-Security / Commit / ...
Votre exigence a été signalée comme un bogue (pas une demande de fonctionnalité) dans jira SEC-2025 a>. Et ils l'ont réparé au printemps 3.2, alors que vous attendez ici pour arriver / résoudre implicitement l'empêche de son conception. P>
Le comportement par défaut consiste à enregistrer le Même le Ce que vous devez faire est, stockez le Gardez une nouvelle copie de Pour faire cela, vous devez lire et comprendre après des implémentations de printemps. P>
httpsessionsecurityContextrepository classe p>
SavetosessionResponsewrapper classe p> li>
ol>
Et vous devrez peut-être remplacer ci-dessus 2 classes en fournissant vos propres implémentations ou en remplacement des implémentations nécessaires. (Et il peut aussi d'autres aussi) p>
Voir: p>
Mise en œuvre de la méthode. P>
Je pense que les documents de Spring Security Docs mentionne clairement de ne pas traiter IMO collez simplement sur les implémentations de sécurité de printemps lorsqu'il n'y a aucune recommandation des ingénieurs de Spring Security pour faire quelque chose par vous-même. Ce que je serre ici peut ne pas corriger, et assurez-vous qu'il n'y aura pas de trous de sécurité et il ne devrait pas casser les autres cas d'utilisation lorsque vous effectuez des modifications non recommandées uniquement pour couvrir un boîtier d'angle.
Je ne ferai jamais cela si cela m'est arrivé, car il est SecurityContext code> dans le
httpsession code> et c'est la seule implémentation de la sécurité de printemps AFAIK fournit en ce moment. P>
SecurityContext Code> est code> threadlocal code> Il partage la même chose qui se trouve dans le
httpsession code>. Donc, lorsque
SecurityContext Code> est nettoyé, il supprimera du
httpsession code>, par conséquent ne sera pas disponible de la session de l'utilisateur entière. P>
SecurityContext Code> en outre dans
httpServletQuest code> (ou quelque chose de lié à la requête HTTP) autre que le
httpsession code> et lisez-le de
httpsession code> et si non trouvé, lisez-le à partir de
httpServletQuest code>. Assurez-vous d'enregistrer une copie
SecurityContext code> dans le
httpservletQuest code>. Lorsque vous vous déconnez-vous, nettoyez le
SecurityContext Code> seulement strong> de httpsession qui se produit actuellement. Dans ce cas, quels que soient les threads d'exécution (liés aux demandes http) auront accès au
SecurityContext Code> via
httpservletQuest code> (si ce n'est pas trouvé dans
httpsession code> - ce qui vous arrive en ce moment) même si l'utilisateur s'est déconnecté. Les nouvelles demandes HTTP suivantes auront besoin d'une authentification car les nouvelles demandes n'ont aucun
SecurityContext code> dans le
httpsession code> (ou
httpservletQuest code>). P>
SecurityContext code> dans chaque
httpServletRQest code> peut être une surcharge uniquement pour adresser un boîtier d'angle. P>
SecurityContextPersisTenceFilter code> Utilisations
SecurityContextrepository code> Pour charger et enregistrer
SecurityContext code>.
HTTPSessIsIsecurityContextrepository Code> est une implication de
SecurityContextrepository code>. p> li>
httpsession code>. C'est pourquoi il y a un
SecurityContext Code>. P>
sec-2025 code> ne directement i> carte de ce problème depuis que le ticket fait référence à l'enregistrement accidentel d'un utilisateur de retour dans i>; Alors que voici ici, nous sommes confrontés au problème où un thread se retrouve "déconnecté" même s'il a commencé comme "connecté". Cela étant dit, votre réponse ressemble à un bon moyen de s'attaquer.
@JLB Vous devez comprendre que, avec cela, vous obtiendrez essentiellement une copie en lecture seule que vous savez que vous savez exister, ce qui signifie qu'aucun code de sécurité de printemps n'utilisera. Et si c'est ce que vous voulez, la question de toute la question est discutable, vous pouvez créer un filtre simple qui stockera le contexte dans la demande / thread local et obtenir le même résultat.
@chimmi Vous avez absolument raison - je me suis rendu compte cela peu de temps après avoir accepté la prime. J'ai une idée que je vais mettre à jour ma réponse avec bientôt - je crois que c'est une approche plus propre, bien que cela soit pris en charge de mon problème.
@chimmi j'ai mis à jour ma réponse avec une solution simple. Cela me traite spécifiquement, mais je pense que cela s'appliquerait à la plupart des cas.
Je suis sûr que je vois aussi le même comportement dans mon application. Malheureusement, tout ce qui a essayé jusqu'à présent n'a pas corrigé (
@Authentiollingprincipal code> méthode param,
principale code> méthode param,
SecurityContexTholder.getContext (). GetAuthentication () code> sont
null code> une fois qu'une déconnexion simultanée est terminée)
En cliquant sur le bouton de déconnexion redirige vers votre page de déconnexion dans un scénario normal?