2017-06-05 3 views
1

Ich arbeite an einem Spring Boot & Spring Security-Anwendung, die JSON Web Tokens verwendet.Zurückkehrende benutzerdefinierte Fehler im Frühjahr Sicherheitsfilter

ich eine Federsicherheitsfilter, die auf das Vorhandensein eines bestehenden JWT überprüft und wenn ja, spritzt eine UsernamePasswordAuthenticationToken:

public class AuthenticationTokenFilter extends UsernamePasswordAuthenticationFilter { 

    @Value("${api.token.header}") 
    String tokenHeader; 

    @Autowired 
    TokenUtility tokenUtility; 

    @Override 
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { 

     HttpServletRequest httpRequest = (HttpServletRequest) servletRequest; 

     String incomingToken = httpRequest.getHeader(tokenHeader); 

     if (SecurityContextHolder.getContext().getAuthentication() == null && incomingToken != null) { 

      UserDetails userDetails = null; 

      try { 

       userDetails = tokenUtility.validateToken(incomingToken); 

      } catch (TokenExpiredException e) { 

       throw new ServletException("Token has expired", e); 
      } 

      if (userDetails != null) { 

       UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); 

       authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpRequest)); 

       SecurityContextHolder.getContext().setAuthentication(authentication); 
      } 
     } 

     filterChain.doFilter(servletRequest, servletResponse); 
    } 
} 

Dieser Filter wie folgt injiziert:

@Configuration 
@EnableWebSecurity 
@EnableGlobalMethodSecurity(prePostEnabled = true) 
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 

    @Autowired 
    UserDetailsService userDetailsService; 

    @Autowired 
    EntryPointUnauthorizedHandler unauthorizedHandler; 

    @Autowired 
    public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception { 

     authenticationManagerBuilder 
          .userDetailsService(userDetailsService) 
          .passwordEncoder(passwordEncoder()); 
    } 

    @Bean 
    public PasswordEncoder passwordEncoder() { 

     return new BCryptPasswordEncoder(); 
    } 

    @Bean 
    @Override 
    public AuthenticationManager authenticationManager() throws Exception { 

     return super.authenticationManager(); 
    } 

    @Bean 
    public AuthenticationTokenFilter authenticationTokenFilter() throws Exception { 

     AuthenticationTokenFilter authenticationTokenFilter = new AuthenticationTokenFilter(); 
     authenticationTokenFilter.setAuthenticationManager(authenticationManager()); 

     return authenticationTokenFilter; 
    } 

    @Override 
    protected void configure(HttpSecurity httpSecurity) throws Exception { 

     httpSecurity 
      .csrf() 
       .disable() 
      .exceptionHandling() 
       .authenticationEntryPoint(unauthorizedHandler) 
       .and() 
      .sessionManagement() 
       .sessionCreationPolicy(SessionCreationPolicy.STATELESS) 
       .and() 
      .authorizeRequests() 
       .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() 
       .antMatchers("/auth/**").permitAll() 
       .anyRequest().authenticated(); 

     // filter injected here 
     httpSecurity.addFilterBefore(authenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class); 
    } 
} 

Wenn ein Benutzer übergibt in einem Token, das abgelaufen ist, erhalten sie die folgende Fehlermeldung:

{ 
    "timestamp":1496424964894, 
    "status":500, 
    "error":"Internal Server Error", 
    "exception":"com.app.exceptions.TokenExpiredException", 
    "message":"javax.servlet.ServletException: Token has expired", 
    "path":"/orders" 
} 

Ich weiß, dass die Spring-Sicherheit die Anfragen abfängt, bevor sie auf die Controller-Ebene gelangen. Daher kann ich meinen vorhandenen @ControllerAdvice nicht verwenden, um diese Ausnahmen zu behandeln.

Meine Frage ist, wie kann ich die Fehlermeldung/Objekt, das hier zurückgegeben wird, anpassen? Anderswo verwende ich ein JSON-serialisiertes POJO, um Fehlermeldungen zurückzugeben, und ich möchte konsistent sein. Ich möchte auch nicht den Benutzer sehen javax.servlet.ServletException

Antwort

1

Wie Sie .exceptionHandling() verwenden Ich glaube, Sie können einen neuen ExceptionHandler konfigurieren;

Eine andere Möglichkeit wäre, die Nachrichten zu überschreiben, die unterschiedlich sein sollen, wie diese post

Verwandte Themen