J'utilise Wicket avec le Wicket Auth Project pour ma couche de présentation et je l'ai donc intégré à Spring Security. C'est la méthode qui est appelée par Wicket pour l'authentification pour moi:
@Override
public boolean authenticate(String username, String password) {
try {
Authentication request = new UsernamePasswordAuthenticationToken(
username, password);
Authentication result = authenticationManager.authenticate(request);
SecurityContextHolder.getContext().setAuthentication(result);
} catch (AuthenticationException e) {
return false;
}
return true;
}
Le contenu (à l'intérieur) de ma configuration XML de Spring Security est:
<http path-type="regex">
<form-login login-page="/signin"/>
<logout logout-url="/logout" />
</http>
<global-method-security secured-annotations="enabled" />
<authentication-manager alias="authenticationManager"/>
<authentication-provider user-service-ref="userService">
<password-encoder ref="bcryptpasswordencoder" />
</authentication-provider>
La section 2.3.6. Session Fixation Attack Protection de la documentation de référence dit:
Les attaques par fixation de session constituent un risque potentiel lorsqu'il est possible pour un attaquant malveillant de créer une session en accédant à un site, puis de persuader un autre utilisateur de se connecter avec la même session (en leur envoyant un lien contenant l'identifiant de session en paramètre, par exemple, pour exemple). Spring Security protège automatiquement contre cela en créant une nouvelle session lorsqu'un utilisateur se connecte. Si vous n'avez pas besoin de cette protection, ou si elle entre en conflit avec une autre exigence, vous pouvez contrôler le comportement à l'aide de l'attribut session-fixation-protection sur lequel a trois options:
- migrateSession - crée une nouvelle session et copie les attributs de session existants dans la nouvelle session. C'est la valeur par défaut.
- aucun - ne faites rien. La session d'origine sera conservée.
- newSession - Créez une nouvelle session "propre", sans copier les données de session existantes.
L'authentification fonctionne, mais comme je suis relativement nouveau dans Spring Security, j'ai quelques questions auxquelles j'ai aussi besoin de réponses:
j_spring_security_check
Et laisser Spring Security effectuer le code d'authentification réel. Je voudrais avoir une protection contre les attaques de fixation de session, vais-je obtenir quand j'effectue une connexion par programmation comme je le fais? Et sinon, que dois-je faire pour l'obtenir? Mise à jour: Pour la protection contre les attaques par fixation de session, il semble que je doive appeler la méthode dans la classe SessionUtils avec la signature startNewSessionIfRequired(HttpServletRequest request, boolean migrateAttributes, SessionRegistry sessionRegistry)
.
Comment obtenir l'instance SessionRegistry que je dois transmettre? Je ne trouve aucun moyen de créer un ID d'alias pour lui, ou comment obtenir son ID ou son nom.
Ce n'est peut-être pas une réponse complète à vos questions, mais peut-être que cela pourrait vous aider.
Le code étant appelé lorsque vous n'utilisez PAS de connexion par programmation, mais un code standard se trouve ici:
org.springframework.security.ui.webapp.AuthenticationProcessingFilter
Je suppose que cela vous a inspiré dans votre code. Cela ressemble assez.
De même, le code exécuté lorsque vous accédez à /j_spring_security_logout
dans l'approche standard, se trouve ici:
org.springframework.security.ui.logout.LogoutFilter
LogoutFilter appelle plusieurs gestionnaires. Le gestionnaire que nous utilisons est appelé: org.springframework.security.ui.logout.SecurityContextLogoutHandler
, vous pouvez donc appeler le même code dans votre approche.
Vous serez en effet ouvert aux attaques de fixations de session. Pour y remédier, vous pourriez à nouveau être "inspiré" par le code Spring. Pour créer une nouvelle session, vous aurez évidemment besoin d'accéder à la httpsession, vous devrez donc peut-être refactoriser.
Si vous voyez la méthode SessionUtils
.startNewSessionIfRequired
.
Cela fera migrer l'authentification vers une nouvelle session. Vous pourriez être en mesure d'appeler cette méthode directement ou bien de remanier un peu le code.
En ce qui concerne la déconnexion programmatique, vous ne pouvez pas vous tromper trop loin en appelant simplement session.invalidate()
lorsque vous devez vous déconnecter. Cela fera tout le nécessaire dans une perspective de sécurité générale, mais gardez à l'esprit que vous devrez peut-être nettoyer certaines choses de la session. Si vous avez un ensemble de filtres très compliqué, etc. et que vous devez vous assurer que l'utilisateur est déconnecté pour le reste de la demande, vous pouvez ajouter:
SecurityContextHolder.getContext().setAuthentication(null);
En ce qui concerne l'interception des URL, vous pouvez simplement les définir sur quelque chose d'inutilisé et l'ignorer! Je ne sais pas si vous pouvez désactiver l'interception dans la configuration - si vous voulez vraiment la supprimer, jetez un œil au AuthenticationProcessingFilter
- vous pouvez personnaliser cela. Si vous faites cela, vous devrez configurer manuellement le XML de sécurité Spring et ne pas utiliser les espaces de noms fournis. Ce n'est pas trop difficile cependant - regardez une documentation plus ancienne et vous verrez comment faire.
J'espère que cela t'aides!
1) Déconnexion programmatique
2) Dites à Spring Security de ne PAS intercepter certaines URL, cela dépend de la configuration de l'espace url de votre application. Si toutes vos pages (à l'exception de/logIn et/logout) vivaient dans le contexte/myApp, vous pouvez le faire:
<http ....>
<intercept-url pattern="/myApp/**" ..>
....
</http>
J'ai eu un problème avec la connexion programmatique. J'ai appelé toutes les méthodes authenticationManager.authenticate(...)
et SecurityContextHolder.getContext().setAuthentication(...)
mais j'ai eu quelques problèmes avec la session. J'ai dû ajouter les lignes suivantes pour gérer correctement la session:
HttpSession session = request.getSession();
session.setAttribute("SPRING_SECURITY_CONTEXT", SecurityContextHolder.getContext());
Cela n'était pas clair à partir de l'exemple de code affiché ci-dessus. Pour plus d'informations, consultez http://forum.springsource.org/showthread.php?t=69761
Pour vous déconnecter par programmation, il est également possible de lancer un org.springframework.security.core.AuthenticationException
. Par exemple, SessionAuthenticationException
. Dans ce cas, ExceptionTranslationFilter
lance la déconnexion.
Vous pouvez essayer ceci
try {
HttpSession session = request.getSession(false);
if (session != null) {
session.invalidate();
}
SecurityContextHolder.clearContext();
} catch (Exception e) {
logger.log(LogLevel.INFO, "Problem logging out.");
}