控制器建议不能在Spring Boot 1.5.3中处理我的异常

时间:2017-06-29 15:25:40

标签: java spring-mvc spring-boot

我在Spring Boot 1.5.3中有api应用程序,我使用安全性登录并通过令牌验证每个请求到我的api。我想在未通过令牌找到用户时添加我的自定义异常和未经授权的异常。添加了带异常的类,但每个响应都有500个代码,但我想要401响应代码。下面是我的代码。

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

public class 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);
}

}

2 个答案:

答案 0 :(得分:0)

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

有关详细信息,请访问 - Exception Handling in Spring MVC

答案 1 :(得分: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);
    }