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
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.
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
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();
}
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:
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