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

如何处理自定义过滤器的异常

巫化
2023-03-14

我有一个验证令牌的自定义筛选器tokenLoginFilter

我的Spring安全

<http pattern="/api/**" use-expressions="true" create-session="stateless" entry-point-ref="restAuthenticationEntryPoint" authentication-manager-ref="authenticationManager">
    <custom-filter ref="tokenLoginFilter" position="FORM_LOGIN_FILTER" />
    <!--<form-login authentication-success-handler-ref="mySuccessHandler" authentication-failure-handler-ref="myFailureHandler" />
    <logout />-->
    <intercept-url pattern="/api/**" access="isAuthenticated()" />
    <intercept-url pattern="/api/login/**" access="permitAll"/>
</http>

令牌登录过滤器

@Component
public class TokenLoginFilter extends GenericFilterBean {
    public static final String DEFAULT_TOKEN_AUTHENTICATION_PARAMETER_NAME = "token";

    @Autowired
    protected AuthenticationManager authenticationManager;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain) throws IOException, ServletException {
        String[] parameters = request.getParameterValues(DEFAULT_TOKEN_AUTHENTICATION_PARAMETER_NAME);

        if (parameters != null && parameters.length > 0) {
            String token = parameters[0];

            if (token != null && !token.isEmpty()) {
                TemporaryAuthenticationToken temporaryAuthenticationToken = new TemporaryAuthenticationToken(token);
                temporaryAuthenticationToken.setDetails(
                        new WebAuthenticationDetailsSource().buildDetails((HttpServletRequest) request));

                SecurityContextHolder.getContext().setAuthentication(
                        authenticationManager.authenticate(temporaryAuthenticationToken));
            }
        }

        chain.doFilter(request, response);
    }
}

在authenticationmanager . authenticate调用中,我从TokenAuthenticationProvider中抛出了BadCredentialsException

令牌身份验证提供程序

@Component
public class TokenAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
    public static final TimeZone DEFAULT_TIME_ZONE = getTimeZone("UTC");

    @Autowired
    protected TemporaryAuthenticationTicketService temporaryAuthenticationTicketService;

    @Autowired
    protected UsersService usersService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        if (authentication instanceof TemporaryAuthenticationToken) {
            TemporaryAuthenticationTicket temporaryAuthenticationTicket = null;
            try {
                temporaryAuthenticationTicket = temporaryAuthenticationTicketService.find(
                        ((TemporaryAuthenticationToken) authentication).getCredentials());
            } catch (EmptyResultDataAccessException ignored) {
            }

            if (temporaryAuthenticationTicket != null) {
                Calendar expirationDate = Calendar.getInstance(DEFAULT_TIME_ZONE);
                expirationDate.setTime(temporaryAuthenticationTicket.getExpirationDate());

                if (Calendar.getInstance(DEFAULT_TIME_ZONE).before(expirationDate)) {
                    Users users = usersService.findUsersUnsecure(temporaryAuthenticationTicket.getUserId());

                    if (users != null) {
                        UserDetails userDetails = new User(users);

                        return createSuccessAuthentication(userDetails, authentication, userDetails);
                    }
                }
            } else {
                throw new BadCredentialsException(messages.getMessage(
                        "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
            }
        }

        return null;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return TemporaryAuthenticationToken.class.isAssignableFrom(authentication);
    }

    @Override
    protected void additionalAuthenticationChecks(UserDetails userDetails,
                                                  UsernamePasswordAuthenticationToken authentication)
            throws AuthenticationException {
    }

    @Override
    protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication)
            throws AuthenticationException {
        return null;
    }
}

Tomcat将此BadCredentialsException解释为错误代码500。

HTTP/1.1 500 Internal Server Error
Connection: close
Content-Language: en
Content-Length: 3152
Content-Type: text/html;charset=utf-8
Date: Tue, 08 Jul 2014 17:37:55 GMT
Server: Apache-Coyote/1.1

<html><head><title>Apache Tomcat/7.0.50 - Error report</title><style><!--H1 {fon
t-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:
22px;} H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525
D76;font-size:16px;} H3 {font-family:Tahoma,Arial,sans-serif;color:white;backgro
und-color:#525D76;font-size:14px;} BODY {font-family:Tahoma,Arial,sans-serif;col
or:black;background-color:white;} B {font-family:Tahoma,Arial,sans-serif;color:w
hite;background-color:#525D76;} P {font-family:Tahoma,Arial,sans-serif;backgroun
d:white;color:black;font-size:12px;}A {color : black;}A.name {color : black;}HR
{color : #525D76;}--></style> </head><body><h1>HTTP Status 500 - Bad credentials
</h1><HR size="1" noshade="noshade"><p><b>type</b> Exception report</p><p><b>mes
sage</b> <u>Bad credentials</u></p><p><b>description</b> <u>The server encounter
ed an internal error that prevented it from fulfilling this request.</u></p><p><
b>exception</b> <pre>org.springframework.security.authentication.BadCredentialsE
xception: Bad credentials
        com.neptune.unsub.security.TokenAuthenticationProvider.authenticate(Toke
nAuthenticationProvider.java:56)
        org.springframework.security.authentication.ProviderManager.authenticate
(ProviderManager.java:156)
        com.neptune.unsub.security.TokenLoginFilter.doFilter(TokenLoginFilter.ja
va:38)
        org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doF
ilter(FilterChainProxy.java:342)
        org.springframework.security.web.context.request.async.WebAsyncManagerIn
tegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
        org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequ
estFilter.java:106)
        org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doF
ilter(FilterChainProxy.java:342)
        org.springframework.security.web.context.SecurityContextPersistenceFilte
r.doFilter(SecurityContextPersistenceFilter.java:87)
        org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doF
ilter(FilterChainProxy.java:342)
        org.springframework.security.web.FilterChainProxy.doFilterInternal(Filte
rChainProxy.java:192)
        org.springframework.security.web.FilterChainProxy.doFilter(FilterChainPr
oxy.java:160)
        org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(Dele
gatingFilterProxy.java:343)
        org.springframework.web.filter.DelegatingFilterProxy.doFilter(Delegating
FilterProxy.java:260)
        org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(H
iddenHttpMethodFilter.java:77)
        org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequ
estFilter.java:106)
        org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(
CharacterEncodingFilter.java:88)
        org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequ
estFilter.java:106)
        com.thetransactioncompany.cors.CORSFilter.doFilter(CORSFilter.java:169)
        com.thetransactioncompany.cors.CORSFilter.doFilter(CORSFilter.java:232)
</pre></p><p><b>note</b> <u>The full stack trace of the root cause is available
in the Apache Tomcat/7.0.50 logs.</u></p><HR size="1" noshade="noshade"><h3>Apac
he Tomcat/7.0.50</h3></body></html>

我试过使用Spring MVC处理异常的方式。

@ControllerAdvice
public class GlobalExceptionHandlers extends ResponseEntityExceptionHandler {

    @ExceptionHandler(BadCredentialsException.class)
    public ResponseEntity<String> badCredentialsException(BadCredentialsException e) {
        return new ResponseEntity<>(e.getMessage(), UNAUTHORIZED);
    }


}

但是异常没有被这个ExceptionHandler处理。我如何让Spring在Tomcat处理之前拦截这个异常?

共有1个答案

景靖琪
2023-03-14

您可以尝试在doFilter方法中捕获异常并通过实现AuthenticationFailureHandler的类来处理它。代码应返回正确的HTTP状态代码以及JSON格式的合适异常。

 @Override
public void onAuthenticationFailure(HttpServletRequest request, 
  HttpServletResponse response,AuthenticationException exception) throws 
  IOException, ServletException {
            response.setContentType( MediaType.APPLICATION_JSON_VALUE);
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);

             ApiError authenticationError = new ApiError(HttpStatus.UNAUTHORIZED, exception.getMessage(), "Not Authenticated");
             ObjectMapper objectMapper = new ObjectMapper();
             response.getWriter().write(objectMapper.writeValueAsString(authenticationError));
};

ApiError是一个自定义类,它包含返回异常场景所需的字段,以及正确的状态代码和异常消息字符串。

附注

您的GlobalExceptionHandler类将不起作用,因为它们已使用ControlllerAddge进行了注释,这意味着从Controller抛出的任何异常都在那里得到处理。

 类似资料:
  • 我是Spring Security的新手。 我有一段代码,我检查是否在请求中传递了授权头,如果缺少,我抛出一个异常。 我的目标是在全球范围内处理所有异常,因此我使用@ControllerAdvice。 注意:我知道@ControllerAdvice对于从这个和这个抛出的控制器之外的异常不起作用,所以我也遵循了这些链接中的建议。 重新验证入口点。Java语言 这是我配置authenticationE

  • 我使用的是Nifi 0.4.1版本。我写自定义代码转换CSV到avro格式。我已经创建了类文件,并能够生成nar文件。将nar文件放置在lib目录中,并重新启动nifi服务器。 任何帮助都很感激.. 谢谢,

  • 演示在网关追加一个header public class CustomFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // 演示在网关追加heade

  • SOFARPC 提供了一套良好的可扩展性机制,为各个模块提供 SPI 的能力。 SOFARPC 对请求与响应的过滤链处理方式是通过多个过滤器 Filter 来进行具体的拦截处理,该部分可由用户自定义 Filter 扩展,自定义 Filter 的执行顺序在内置 Filter 之后。具体方式如下: Bolt Filter 新建自定义 Filter 。 public class CustomFilter

  • 我正在使用Spring4和Tomcat。问题是有时我不得不在我的筛选器中抛出一个(自定义的)RuntimeException(控件甚至还没有到达控制器)。问题是,由于我没有抛出tomcat理解的异常,它被转换为500(内部服务器错误)。我相信403禁止会比500好(对于我的定制例外)。我查看了和注释。但只有当控件到达控制器时,这些才起作用。 到目前为止,我在筛选器的中将状态手动设置为403。有没有

  • 问题内容: 我试图在Log4J2中实现和配置自定义过滤器- 基于ThresholdFilter,但打算做更多。我已经看到了有关自定义追加程序的主题,这些主题遵循相同的插件注释语法,但是还没有找到有关自定义拟合程序的主题。 MyCustomFilter.java (基于ThresholdFilter) log4j2.xml LoggingRunner.java 配置语法似乎与Apache文档中的语法