web-dev-qa-db-fra.com

Authentification de jeton de sécurité Spring - Service JSON RESTful

Je cherche à utiliser Spring Security pour une application Spring MVC qui sera strictement un service Web JSON. J'ai fait quelques recherches et lu quelques articles mais je n'ai rien trouvé de vraiment complet. Je veux que l'application soit complètement sans état et utilise une authentification basée sur des jetons. Je ne veux pas que l'application Spring MVC ait des formulaires ou des formulaires utilisés pour s'authentifier. Il doit prendre strictement les demandes et les données en JSON et renvoyer les réponses JSON.

Il y aura une Angular JS qui devra envoyer le nom d'utilisateur et le mot de passe et obtenir le jeton de l'application à utiliser dans les demandes séquentielles. À un certain point, il peut y avoir Android clients qui accèdent également à ce service Web.

Je suppose que Spring Security a sa manière interne de mapper un jeton à une session utilisateur, ce qui signifie qu'il sait que le jeton XXXXXXXXXXXX est l'utilisateur administrateur Bob et le jeton AAAAAAAAAA est l'utilisateur standard Joe. Cependant, je n'ai pas beaucoup d'expérience avec Spring Security, donc je ne sais pas comment tout cela se combine. Je veux toujours pouvoir utiliser des annotations sécurisées sur les méthodes de contrôleur et de service.

Existe-t-il un moyen d'accomplir cela dans Spring Security?

Cette question semble être un bon point de départ, mais je ne suis pas sûr que cela fonctionnera comme je l'ai envisagé authentification RESTful via Spring .

23
greyfox

Ce sera un bon point de départ avec Spring-Rest-Boilerplate .

  1. Pour la première fois, vous devez utiliser l'authentification de base http, puis vous connecter (envoyer un nom d'utilisateur/mot de passe) et cela retournera le jeton.
  2. Dans une demande ultérieure, vous utiliserez ce jeton pour l'authentification.
  3. Vous devrez ajouter un filtre à la chaîne qui fera cette authentification basée sur un jeton.

Vous devez trouver un format de jeton et un cryptage pour celui-ci. Idéalement, vous devez également conserver une expiration pour le jeton, l'expiration ainsi que le nom d'utilisateur peuvent faire partie du jeton. un algorithme de cryptage une fonction de hachage cryptographique comme MD5 et obtenir le hachage de l'ensemble du jeton.

Edit : Comme indiqué par Maciej Stępyra MD5 semble être cassé et il est conseillé d'utiliser des fonctions de hachage plus fortes comme SHA-256.

La sécurité de Spring par défaut vous redirigera vers une page de connexion, mais cela n'a pas de sens en cas de REST alors utilisez un AuthenticationEntryPoint personnalisé dans la configuration (Réf exemple de code github).

J'utilisais ce format pour mon jeton: token:username:hash:expiry

hachage = MD5 (nom d'utilisateur + magickey)

expiration = current_timestamp + mins_to_expiry

 <security:http realm="Protected API" use-expressions="true" auto-config="false" create-session="always" entry-point-ref="**CustomAuthenticationEntryPoint**">
        <security:custom-filter ref="**authenticationTokenProcessingFilter**" position="PRE_AUTH_FILTER" />
        <security:intercept-url pattern="/**" access="isAuthenticated()" />
 </security:http>

NB: Merci dhavaln pour le code. Je l'ai utilisé comme référence et développé une chose similaire.

18
M4ver1k

Dans mon cas, j'ai trouvé plus facile de remplacer le org.springframework.security.web.context.SecurityContextRepository dans org.springframework.security.web.context.SecurityContextPersistenceFilter avec une implémentation qui partage le SecurityContext entre plusieurs nœuds Tomcat. Le client continue d'envoyer un jeton semblable à jsessionid mais je peux faire un équilibrage de charge à tour de rôle simple et ne pas avoir à me soucier de la réplication de session.

1
user2560528

"Je veux que l'application soit complètement apatride"

Je reconsidérerais ce que vous essayez de faire. Il y a une raison pour laquelle vous ne pouvez pas trouver de bons exemples de votre solution: vous ne pouvez tout simplement pas avoir une application à la fois sans état et sécurisée. De plus, si vous stockez les jetons quelque part, vous n'êtes pas apatride. Même si vous ne stockez pas les jetons (comme utiliser JWT pour les encoder), vous devez vous protéger contre les attaques CSRF si les utilisateurs y accèdent dans un navigateur Web. Si vous suivez votre itinéraire, attendez-vous à écrire beaucoup de code de sécurité personnalisé (ce qui est une mauvaise chose). Voir une discussion à ce sujet ici: https://spring.io/blog/2015/01/12/the-login-page-angular-js-and-spring-security-part-ii

1
user64141