web-dev-qa-db-fra.com

Comment sécuriser l'API REST avec Spring Boot et Spring Security?

Je sais que la sécurisation de l'API REST est un sujet largement commenté, mais je ne suis pas en mesure de créer un petit prototype qui répond à mes critères (et je dois confirmer que ces critères sont réalistes). Il y a tellement d'options pour sécuriser les ressources et travailler avec Spring, il faut que je clarifie si mes besoins sont réalistes.

Mes exigences

  • Authentificateur basé sur les jetons - les utilisateurs fourniront leurs informations d'identification et obtiendront un jeton d'accès unique et limité dans le temps. Je souhaite gérer la création de jetons, vérifier la validité, l'expiration dans ma propre implémentation.
  • Certaines ressources REST seront publiques - inutile de vous authentifier,
  • Certaines ressources ne seront accessibles qu’aux utilisateurs disposant de droits d’administrateur,
  • Les autres ressources seront accessibles après autorisation pour tous les utilisateurs.
  • Je ne veux pas utiliser l'authentification de base
  • Configuration du code Java (pas XML)

Statut actuel

Mon API REST fonctionne très bien, mais je dois maintenant la sécuriser. Lorsque je cherchais une solution, j'ai créé un filtre javax.servlet.Filter:

  @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;

        String accessToken = request.getHeader(AUTHORIZATION_TOKEN);
        Account account = accountDao.find(accessToken);

        if (account == null) {    
            throw new UnauthorizedException();    
        }

        chain.doFilter(req, res);

    }

Mais cette solution avec javax.servlet.filters ne fonctionne pas comme il me faut car il existe un problème de gestion des exceptions via @ControllerAdvice avec Spring servlet dispatcher.

Ce dont j'ai besoin

J'aimerais savoir si ces critères sont réalistes et obtenir de l'aide, comment commencer à sécuriser l'API REST avec Spring Security. J'ai lu de nombreux tutoriels (par exemple, Spring Data REST + Spring Security ), mais ils fonctionnent tous dans une configuration très basique - les utilisateurs avec leurs informations d'identification sont stockés dans mémoire dans la configuration et je dois travailler avec le SGBD et créer mon propre authentificateur.

S'il vous plaît, donnez-moi quelques idées pour commencer.

74
Artegon

Authentification basée sur les jetons - les utilisateurs fourniront leurs informations d'identification et obtiendront un jeton d'accès unique et limité dans le temps. Je souhaite gérer la création de jetons, vérifier la validité, l'expiration dans ma propre implémentation.

En fait, utilisez le filtre pour le jeton Auth - le meilleur moyen dans ce cas

Finalement, vous pouvez créer CRUD via Spring Data pour gérer les propriétés de Token comme pour expirer, etc.

Voici mon filtre de jeton: http://Pastebin.com/13WWpLq2

Et mise en œuvre du service de jetons

http://Pastebin.com/dUYM555E

Certaines REST ressources seront publiques - inutile de vous authentifier

Ce n'est pas un problème, vous pouvez gérer vos ressources via la configuration de sécurité Spring comme ceci: .antMatchers("/rest/blabla/**").permitAll()

Certaines ressources ne seront accessibles qu’aux utilisateurs disposant de droits d’administrateur,

Jetez un coup d'œil à l'annotation @Secured to class. Exemple:

@Controller
@RequestMapping(value = "/adminservice")
@Secured("ROLE_ADMIN")
public class AdminServiceController {

L'autre ressource sera accessible après autorisation pour tous les utilisateurs.

Retour à la configuration de Spring Security, vous pouvez configurer votre URL de la manière suivante:

    http
            .authorizeRequests()
            .antMatchers("/openforall/**").permitAll()
            .antMatchers("/alsoopen/**").permitAll()
            .anyRequest().authenticated()

Je ne veux pas utiliser l'authentification de base

Oui, via le filtre à jeton, vos utilisateurs seront authentifiés.

Configuration du code Java (pas XML)

Retour aux mots ci-dessus, regardez @EnableWebSecurity. Votre cours sera:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {}

Vous devez remplacer la méthode configure . Code ci-dessous, juste par exemple, comment configurer des correspondants. Cela provient d'un autre projet.

    @Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
            .antMatchers("/assets/**").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin()
                .usernameParameter("j_username")
                .passwordParameter("j_password")
                .loginPage("/login")
                .defaultSuccessUrl("/", true)
                .successHandler(customAuthenticationSuccessHandler)
                .permitAll()
            .and()
                .logout()
                .logoutUrl("/logout")
                .invalidateHttpSession(true)
                .logoutSuccessUrl("/")
                .deleteCookies("JSESSIONID")
                .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
            .and()
                .csrf();
}
60
Oleksandr Loushkin

La sécurité Spring est également très utile pour fournir l’authentification et l’autorisation aux URL REST. Nous n'avons pas besoin de spécifier d'implémentations personnalisées.

Tout d'abord, vous devez spécifier l'entrée-point-ref à restAuthenticationEntryPoint dans votre configuration de sécurité, comme indiqué ci-dessous.

 <security:http pattern="/api/**" entry-point-ref="restAuthenticationEntryPoint" use-expressions="true" auto-config="true" create-session="stateless" >

    <security:intercept-url pattern="/api/userList" access="hasRole('ROLE_USER')"/>
    <security:intercept-url pattern="/api/managerList" access="hasRole('ROLE_ADMIN')"/>
    <security:custom-filter ref="preAuthFilter" position="PRE_AUTH_FILTER"/>
</security:http>

L'implémentation de restAuthenticationEntryPoint pourrait être la suivante.

 @Component
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {

   public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException ) throws IOException {
      response.sendError( HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized" );
   }
}

Après cela, vous devez spécifier RequestHeaderAuthenticationFilter. Il contient la clé RequestHeader. Ceci est essentiellement utilisé pour identifier l'authentification de l'utilisateur. Généralement, RequestHeader transporte ces informations lors des appels REST. Par exemple, considérez ci-dessous le code

   <bean id="preAuthFilter" class="org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter">
    <property name="principalRequestHeader" value="Authorization"/>
    <property name="authenticationManager" ref="authenticationManager" />
  </bean>

Ici,

<property name="principalRequestHeader" value="Authorization"/>

"Autorisation" est la clé présentée à la demande entrante. Il contient les informations d'authentification de l'utilisateur requis. Vous devez également configurer le fournisseur PreAuthenticatedAuthenticationProvider pour répondre à nos exigences.

   <bean id="preauthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<property name="preAuthenticatedUserDetailsService">
  <bean id="userDetailsServiceWrapper"
      class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
    <property name="userDetailsService" ref="authenticationService"/>
  </bean>
</property>
</bean>

Ce code fonctionnera pour sécuriser les URL REST au moyen de l'authentification et de l'autorisation sans implémentations personnalisées.

Pour le code complet, veuillez trouver le lien ci-dessous:

https://github.com/srinivas1918/spring-rest-security

4
Nalla Srinivas

Je cherche aussi depuis longtemps. Je travaille sur un projet similaire.J'ai découvert que Spring dispose d'un module pour implémenter une session via redis. Cela semble facile et utile. Je vais ajouter à mon projet aussi. Peut être utile:

http://docs.spring.io/spring-session/docs/1.2.1.BUILD-SNAPSHOT/reference/html5/guides/rest.html

0
serkan ersoy