J'ai la configuration Spring Security suivante:
httpSecurity
.csrf()
.disable()
.exceptionHandling()
.authenticationEntryPoint(unauthorizedHandler)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/**").fullyAuthenticated()
.and()
.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
authenticationTokenFilterBean()
est appliqué même sur les ordinateurs d'extrémité qui ne correspondent pas à l'expression /api/**
. J'ai aussi essayé d'ajouter le code de configuration suivant
@Override
public void configure(WebSecurity webSecurity) {
webSecurity.ignoring().antMatchers("/some_endpoint");
}
mais cela n'a toujours pas résolu mon problème. Comment puis-je dire à Spring Security d'appliquer des filtres uniquement aux systèmes d'extrémité correspondant à l'expression d'URI sécurisée? Je vous remercie
J'ai une application avec les mêmes exigences et pour la résoudre, j'ai essentiellement limité Spring Security à un modèle de correspondance de fourmi donné (à l'aide de antMatcher
) comme suit:
http.antMatcher("/api/**").authorizeRequests() //
.anyRequest().authenticated() //
.and()
.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
Vous pouvez le lire comme suit: pour http
n'appeler ces configurations que sur les requêtes correspondant au modèle ant, /api/**
autorisant any request
à authenticated
utilisateurs and
add filter
authenticationTokenFilterBean()
before
UsernamePasswordAuthenticationFilter
. Pour toutes les autres demandes, cette configuration n'a aucun effet.
Si vous utilisez le
.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
Vous pouvez définir dans le constructeur le chemin spécifique auquel il s'appliquera:
public class JwtAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
super("/api/**");
this.setAuthenticationManager(authenticationManager);
}
@Override
protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) {
return super.requiresAuthentication(request, response);
}
La méthode requireAuthentication sera utilisée pour savoir si ce terminal a besoin d'une authentification
Je pense avoir trouvé un moyen de le résoudre. J'ai JwtTokenAuthenticationProcessingFilter
qui est un AbstractAuthenticationProcessingFilter
. Je veux qu'il authentifie la demande s'il y a un jeton dans la tête mais ne bloque pas la demande en cas d'échec. Tout ce dont vous avez besoin est de réécrire ledoFilteret d'appeler lechain.doFilter
peu importe le résultat de l'authentification (l'invocation de l'unsuccessfulAuthentication est facultative). Voici une partie de mon code.
public class JwtTokenAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter {
private final TokenExtractor tokenExtractor;
@Autowired
public JwtTokenAuthenticationProcessingFilter(TokenExtractor tokenExtractor, RequestMatcher matcher) {
super(matcher);
this.tokenExtractor = tokenExtractor;
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException,
ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
if (!this.requiresAuthentication(request, response)) {
chain.doFilter(request, response);
} else {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Request is to process authentication");
}
boolean success = true;
Authentication authResult = null;
try {
authResult = this.attemptAuthentication(request, response);
} catch (InternalAuthenticationServiceException var8) {
this.logger.error("An internal error occurred while trying to authenticate the user.", var8);
success = false;
} catch (AuthenticationException var9) {
success = false;
}
if (success && null != authResult) {
this.successfulAuthentication(request, response, chain, authResult);
}
// Please ensure that chain.doFilter(request, response) is invoked upon successful authentication. You want
// processing of the request to advance to the next filter, because very last one filter
// FilterSecurityInterceptor#doFilter is responsible to actually invoke method in your controller that is
// handling requested API resource.
chain.doFilter(request, response);
}
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
String tokenPayload = request.getHeader(WebSecurityConfig.AUTHENTICATION_HEADER_NAME);
RawAccessJwtToken token = new RawAccessJwtToken(tokenExtractor.extract(tokenPayload));
return getAuthenticationManager().authenticate(new JwtAuthenticationToken(token));
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
Authentication authResult) throws IOException, ServletException {
SecurityContext context = SecurityContextHolder.createEmptyContext();
context.setAuthentication(authResult);
SecurityContextHolder.setContext(context);
}
}