2017-06-29 76 views
0

我在Spring Boot 1.5.3中有其他api应用程序,我使用安全性通过令牌对我的api登录和验证每个请求。当用户找不到令牌时,我想添加我的自定义异常与未经授权的异常。有异常的类被添加,但是每个响应都有500个代码,但我需要401个响应代码。下面是我的代码。控制器建议不处理我在Spring Boot 1.5.3中的异常

StatelessAuthenticationFilter

  public class StatelessAuthenticationFilter extends GenericFilterBean { 

      private final TokenAuthenticationService    tokenAuthenticationService; 

      public StatelessAuthenticationFilter(TokenAuthenticationService taService) { 
      this.tokenAuthenticationService = taService; 
      } 

      @Override 
      public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { 
      SecurityContextHolder.getContext().setAuthentication(tokenAuthenticationService.getAuthentication((HttpServletRequest) req)); 
      chain.doFilter(req, res); 
      } 

StatelessLoginFilter

  public class StatelessLoginFilter extends AbstractAuthenticationProcessingFilter { 

      private final TokenAuthenticationService tokenAuthenticationService; 
      private final UserServiceImpl userService; 

      public StatelessLoginFilter(String urlMapping, TokenAuthenticationService tokenAuthenticationService, 
          UserServiceImpl userDetailsService, AuthenticationManager authManager) { 
      super(new AntPathRequestMatcher(urlMapping)); 
      this.userService = userDetailsService; 
      this.tokenAuthenticationService = tokenAuthenticationService; 
      setAuthenticationManager(authManager); 
      } 

      @Override 
      public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) 
       throws AuthenticationException, IOException, ServletException { 

      String headerCredentials = request.getHeader("BasicAuth"); 

      if (headerCredentials == null) { 
       throw new BadCredentialsException("No header in request"); 
      } 

      String credentials = new String(Base64.decodeBase64(headerCredentials), "UTF-8"); 
      if (!credentials.contains((":"))) { 
       throw new BadCredentialsException("Wrong header"); 
      } 
      String [] credentialsArray = credentials.split(":"); 

      String login = credentialsArray[0]; 
      String password = credentialsArray[1]; 

      final UsernamePasswordAuthenticationToken loginToken = new UsernamePasswordAuthenticationToken(login, password); 
      return getAuthenticationManager().authenticate(loginToken); 
      } 

      @Override 
      protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, 
            FilterChain chain, Authentication authentication) throws IOException, ServletException { 

      // Lookup the complete User2 object from the database and create an Authentication for it 
      final User authenticatedUser = userService.loadUserByUsername(authentication.getName()); 
      final UserAuthentication userAuthentication = new UserAuthentication(authenticatedUser); 

      // Add the custom token as HTTP header to the response 
      tokenAuthenticationService.addAuthentication(response, userAuthentication); 

      // Add the authentication to the Security context 
      SecurityContextHolder.getContext().setAuthentication(userAuthentication); 
      } 

MyOwnException

  public class MyOwnException extends RuntimeException { 

      public MyOwnException(String message) { 
      super(message); 

      } 

RestResponseEntityExceptionHandler

  @ControllerAdvice 
     public class RestResponseEntityExceptionHandler extends DefaultHandlerExceptionResolver { 

      @ExceptionHandler(MyOwnException.class) 
      void handleMyOwnException(HttpServletResponse response) throws IOException { 
      response.sendError(HttpStatus.UNAUTHORIZED.value()); 
      } 
     } 

StatelessAuthenticationSecurityConfig

 @EnableWebSecurity 
     @Configuration 
     @Order(1) 
     public class StatelessAuthenticationSecurityConfig extends WebSecurityConfigurerAdapter { 

      @Autowired 
      private UserServiceImpl userService; 

      @Autowired 
      private TokenAuthenticationService tokenAuthenticationService; 

      public StatelessAuthenticationSecurityConfig() { 
      super(true); 
      } 

      @Override 
      protected void configure(HttpSecurity http) throws Exception { 
      http.cors() 
       .and() 
       .authorizeRequests() 
       .antMatchers(HttpMethod.POST, "/login").permitAll() 
       .antMatchers("/admin/**").hasRole("ADMIN") 
       .anyRequest().hasRole("USER") 
       .anyRequest().hasRole("ADMIN").and() 

       // custom JSON based authentication by POST of {"username":"<name>","password":"<password>"} which sets the token header upon authentication 
       .addFilterBefore(new StatelessLoginFilter("/login", tokenAuthenticationService, userService, authenticationManager()), UsernamePasswordAuthenticationFilter.class) 

       // custom Token based authentication based on the header previously given to the client 
       .addFilterBefore(new StatelessAuthenticationFilter(tokenAuthenticationService), UsernamePasswordAuthenticationFilter.class); 
      } 

      @Bean 
      @Override 
      public AuthenticationManager authenticationManagerBean() throws Exception { 
      return super.authenticationManagerBean(); 
      } 

      @Override 
      protected void configure(AuthenticationManagerBuilder auth) throws Exception { 
      auth.userDetailsService(userService).passwordEncoder(new BCryptPasswordEncoder()); 
      } 

      @Bean 
      CorsConfigurationSource corsConfigurationSource() { 
      CorsConfiguration configuration = new CorsConfiguration(); 
      configuration.addAllowedOrigin("*"); 
      configuration.setAllowedMethods(Arrays.asList("GET", "POST", "DELETE", "OPTIONS")); 
      configuration.setExposedHeaders(Arrays.asList("x-auth-token")); 
      configuration.addAllowedHeader("*"); 
      UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); 
      source.registerCorsConfiguration("/**", configuration); 
      return source; 
      } 

      @Override 
      protected UserServiceImpl userDetailsService() { 
      return userService; 
      } 

VoteApp

 @SpringBootApplication 
     public class VoteApp { 
      public static void main(String[] args) { 
      SpringApplication.run(VoteApp.class, args); 
      } 

      @Bean 
      public Filter characterEncodingFilter() { 
      CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter(); 
      characterEncodingFilter.setEncoding("UTF-8"); 
      characterEncodingFilter.setForceEncoding(true); 
      return characterEncodingFilter; 
      } 
     } 

UserServiceImpl

@Service 

公共类UserServiceImpl实现org.springframework.security.core.userdetails.UserDetailsS​​ervice {

@Autowired 
private UserRepository userRepository; 

@Override 
public final User loadUserByUsername(String username) throws UsernameNotFoundException { 
    final User user = userRepository.findByUsername(username); 
    if (user == null) { 
     throw new UsernameNotFoundException("user not found"); 
    } 
    return user; 
} 

public User findByToken(String token) throws MyOwnException { 
    final User user = userRepository.findByToken(token); 
    if (user == null) { 
     throw new MyOwnException("user by token not found"); 
    } 
    return user; 
} 

public void save(User user) { 
    userRepository.save(user); 
} 

}

+0

你能分享抛出异常的代码吗? – Leffchik

+0

我附上上面。 –

+0

我觉得问题是春天安全,但我不知道如何解决它。 –

回答

0

显然@ControllerAdvice无法处理您的异常,因为控制方法还没有被调用呢。我的意思是你在servlet过滤器中抛出异常。我认为你将不得不手动捕捉它,像这样运行:

public class StatelessAuthenticationFilter extends GenericFilterBean { 

    private final TokenAuthenticationService tokenAuthenticationService; 

    public StatelessAuthenticationFilter(TokenAuthenticationService taService) { 
     this.tokenAuthenticationService = taService; 
    } 

    @Override 
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { 
     Authentication auth = null; 
     try { 
      auth = tokenAuthenticationService.getAuthentication((HttpServletRequest) req); 
     } catch (MyOwnException e) { 
      SecurityContextHolder.clearContext(); 
      response.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage()); 
      return; 
     } 
     SecurityContextHolder.getContext().setAuthentication(auth); 
     chain.doFilter(req, res); 
    } 
+0

Thx,它的工作原理:) –

0

将@ResponseStatus注释添加到您的控制器建议的异常处理程序中。

欲了解更多信息,请访问 - Exception Handling in Spring MVC

+0

我添加了@ResponseStatus(HttpStatus.CONFLICT),但不起作用。 –