当前位置: 首页 > 知识库问答 >
问题:

控制器建议不要在spring boot 1.5.3中处理我的异常

楚昀
2023-03-14

我在spring boot 1.5.3中有rest api应用程序,我使用安全性登录并通过令牌对我的api验证每个请求。我想添加我的自定义异常与未经授权的异常时,用户没有找到由令牌。类添加了异常,但每个响应都有500个代码,但我想要401个响应代码。Belowe是我的密码。

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);

            }

RESTResponseEntityExceptionHandl

         @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.UserDetailsService{

@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);
}

}

共有1个答案

甄飞飙
2023-03-14

显然,@controlleradvice无法处理您的异常,因为尚未调用controller方法。我的意思是在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);
    }
 类似资料:
  • 我正在使用Spring MVC 4.1为restful Web服务添加速率限制。 我创建了一个注释,可以应用于控制器方法。Spring AOP方面会拦截对这些方法的调用,并在请求过多时引发异常: 这一切都非常有效,除非控制器方法的参数标记为,例如: 问题:如果验证失败,验证器会抛出由@ExceptionHandler处理的,它会向客户端返回错误响应,永远不会触发我的,因此绕过速率限制。 如何以优先

  • 你们能分享一些关于如何在Spring MVC中设计一个处理异常的良好实现的建议吗?以下是我在网上花了一些时间试图找出处理异常的合适或更好的实现后的一些想法。 以下是我正在进行的项目的一些背景: 使用的MVC框架是Spring Boot Web。与其他使用 Spring MVC 的项目类似,我将代码分为几层:控制器、服务和模型。 在控制器中,主要是验证来自视图(前端)层的表单输入并执行一些业务逻辑。

  • 我有一个spring-boot应用程序,没有任何控制器类。如何为该应用程序编写异常处理程序。用@ControllerAdvice注释的异常处理程序类不起作用。

  • 我有spring boot命令行应用程序,我希望以这样的方式处理应用程序错误,即允许我通过退出代码将它们传播给用户,再加上错误日志中一些合理的错误消息(而不仅仅是无意义的stacktrace)。我在文档中发现应用程序异常应该实现ExitCodeGenerator,因此我遵循了这个建议。但是我应该在公共void run(string...args)方法中捕获这个异常还是spring boot将为我处

  • 我的rest控制器包含以下post映射: ServiceExceptionn是特定于我的应用程序的自定义异常。 控制器建议如下所示: 应用yml包含以下属性: 如果我使用大小大于2MB的文件调用rest api,则会出现以下异常: 我在这里面临的问题是:控制器的建议没有按照预期工作。handleFileTooLargeException-必须执行此方法,因为它使用特定异常类型中提到的Excepti

  • spring MVC中controllin异常流的良好实践是什么? 假设我有一个DAO类,它将对象保存到数据库中,但如果违反了某些规则,例如名称太长、年龄太低,则抛出异常, 现在,如果我想保存名称超过10的A,它应该抛出异常。 但是有一个dataManipulator对象 和控制器 我希望在不抛出异常的情况下保留控制器(我听说这是一个很好的做法)。 但我的问题是,在这种情况下,A\u Data\u