web-dev-qa-db-fra.com

Utilisation programmatique de Spring Security

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:

  • Normalement, pour la connexion, je voudrais POST les informations d'authentification sur 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?
  • Comment effectuer une déconnexion programmatique?
  • Comme j'utiliserai la connexion et la déconnexion programmatiques, comment désactiver Spring pour intercepter ces URL?

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.

37
user14070

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.

23
Grzegorz Oledzki

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!

8
Pablojim

1) Déconnexion programmatique

  1. appeler HttpServletRequest.getSession (false) .invalidate
  2. appeler SecurityContextHolder.clearContext ()

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>
6
Gandalf

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

1
velaia

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.

0
viator

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.");
    }
0
Chandra