Spring 即使OAuth2验证失败,如何记录http请求/响应正文?

Spring 即使OAuth2验证失败,如何记录http请求/响应正文?,spring,spring-boot,spring-mvc,spring-security,oauth-2.0,Spring,Spring Boot,Spring Mvc,Spring Security,Oauth 2.0,我需要将Spring Boot MVC应用程序的每个请求和响应主体索引(记录)到Elasticsearch应用程序中。我在过滤器中实现了日志记录,使其成为最高优先级(顺序为1) 我的应用程序充当OAuth2资源服务器,它在其中验证来自Auth服务器的令牌。问题是,如果令牌验证失败,则请求不会进入筛选器,从而跳过请求和响应日志索引部分。如果令牌验证失败,则当前逻辑将在部件中引发异常: public class MyJwtAccessTokenConverter extends JwtAccessT

我需要将Spring Boot MVC应用程序的每个
请求
响应
主体索引(记录)到Elasticsearch应用程序中。我在过滤器中实现了日志记录,使其成为最高优先级(顺序为1)

我的应用程序充当OAuth2资源服务器,它在其中验证来自Auth服务器的令牌。问题是,如果令牌验证失败,则请求不会进入筛选器,从而跳过请求和响应日志索引部分。如果令牌验证失败,则当前逻辑将在部件中引发异常:

public class MyJwtAccessTokenConverter extends JwtAccessTokenConverter {
                @Override
                protected Map<String, Object> decode(String token) {
                   //logic to throw token error
           }
   }
公共类MyJwtAccessTokenConverter扩展了JwtAccessTokenConverter{
@凌驾
受保护地图解码(字符串标记){
//抛出令牌错误的逻辑
}
}
我想索引请求和响应主体,即使令牌未经验证。我怎么做?是否有任何方法将筛选器置于令牌验证之前,或者有任何其他特定方法记录请求和响应

编辑: 我的ResourceServer配置如下:

@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Log4j2
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

    @Value("${spring.application.name}")
    public String applicationResourceID;

    @Value(" ${key.config.oauth2.publicKey}")
    private String publicKey;

    @Value("jwt.aes.encrypt.keyValue")
    String jwtAesEncryptionKey;

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers(
                        "test/**"
                ).permitAll()
                .and().authorizeRequests().anyRequest().authenticated().and()
                .cors().and()
                .csrf().disable()
                .httpBasic().disable()
                .exceptionHandling()
                .authenticationEntryPoint(
                        (request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED)
                )
                .accessDeniedHandler(
                        (request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED)
                );
    }

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        OAuth2AuthenticationEntryPoint authenticationEntryPoint = new OAuth2AuthenticationEntryPoint();
        authenticationEntryPoint.setExceptionTranslator(oauth2ResponseExceptionTranslator());
        resources.authenticationEntryPoint(authenticationEntryPoint);

        OAuth2AccessDeniedHandler accessDeniedHandler = new OAuth2AccessDeniedHandler();
        accessDeniedHandler.setExceptionTranslator(oauth2ResponseExceptionTranslator());
        resources.accessDeniedHandler(accessDeniedHandler);

        resources.authenticationEntryPoint(authenticationEntryPoint)
                .accessDeniedHandler(accessDeniedHandler)
                .resourceId(applicationResourceID)
                .tokenStore(tokenStore());
    }

    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(jwtAccessTokenConverter());
    }

    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        MyJwtAccessTokenConverter converter = new MyJwtAccessTokenConverter(jwtAesEncryptionKey);
        converter.setVerifierKey(publicKey);
        return converter;
    }


    @Bean
    @Profile(value = {"local"})
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("http://localhost:4200"));
        configuration.setAllowedHeaders(Arrays.asList("authorization", "content-type"));
        configuration.setAllowedMethods(Arrays.asList("GET", "POST"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }


    @Bean
    public WebResponseExceptionTranslator oauth2ResponseExceptionTranslator() {
        return new DefaultWebResponseExceptionTranslator() {

            @Override
            public ResponseEntity<OAuth2Exception> translate(Exception e) throws Exception {

                try {

                    log.info("Oauth2ExceptionTranslatorConfiguration", e);

                    ResponseEntity<OAuth2Exception> responseEntity = super.translate(e);
                    OAuth2Exception oAuth2ExceptionBody = responseEntity.getBody();
                    HttpStatus statusCode = responseEntity.getStatusCode();

                    OAuth2Exception myOAuth2Response = OAuth2Exception.create(oAuth2ExceptionBody.getOAuth2ErrorCode(), getMessage(oAuth2ExceptionBody));
                    myOAuth2Response.addAdditionalInformation("message", myOAuth2Response.getMessage());
                    myOAuth2Response.addAdditionalInformation("isSuccess", "false");

                    HttpHeaders headers = new HttpHeaders();
                    headers.setAll(responseEntity.getHeaders().toSingleValueMap());

                    return new ResponseEntity<>(myOAuth2Response, headers, statusCode);
                } catch (Exception ex) {
                    log.info("Oauth2ExceptionTranslatorConfiguration", ex);
                    return new ResponseEntity<>(new OAuth2Exception("Error"), null, HttpStatus.INTERNAL_SERVER_ERROR);
                }

            }
        };
    }

    private String getMessage(OAuth2Exception oAuth2Exception) {
        if (oAuth2Exception instanceof InvalidTokenException) {
            return "Invalid Token";
        } else if (oAuth2Exception instanceof InvalidGrantException) {
            return "Invalid Username or password";
        } else if (oAuth2Exception instanceof InvalidRequestException) {
            return "Invalid Request";
        }

        return oAuth2Exception.getOAuth2ErrorCode();
    }

}
@配置
@EnableResourceServer
@EnableGlobalMethodSecurity(Prespenabled=true)
@Log4j2
公共类ResourceServerConfiguration扩展了ResourceServerConfigurerAdapter{
@值(${spring.application.name}”)
公共字符串applicationResourceID;
@值(${key.config.oauth2.publicKey}”)
私有字符串公钥;
@值(“jwt.aes.encrypt.keyValue”)
字符串JWTAESEEncryptionKey;
@凌驾
public void configure(HttpSecurity http)引发异常{
http.authorizeRequests()
蚂蚁配对者(
“测试/**”
).permitAll()
.和().authorizeRequests().anyRequest().authorized()和()
.cors()和()
.csrf().disable()
.httpBasic().disable()
.例外处理()
.authenticationEntryPoint(
(请求、响应、authException)->response.sendError(HttpServletResponse.SC\u未经授权)
)
.accessDeniedHandler(
(请求、响应、authException)->response.sendError(HttpServletResponse.SC\u未经授权)
);
}
@凌驾
public void configure(ResourceServerSecurityConfigure资源)引发异常{
OAuth2AuthenticationEntryPoint authenticationEntryPoint=新的OAuth2AuthenticationEntryPoint();
authenticationEntryPoint.setExceptionTranslator(oauth2ResponseExceptionTranslator());
authenticationEntryPoint(authenticationEntryPoint);
OAuth2AccessDeniedHandler accessDeniedHandler=新的OAuth2AccessDeniedHandler();
accessDeniedHandler.setExceptionTranslator(oauth2ResponseExceptionTranslator());
resources.accessDeniedHandler(accessDeniedHandler);
resources.authenticationEntryPoint(authenticationEntryPoint)
.accessDeniedHandler(accessDeniedHandler)
.resourceId(applicationResourceID)
.tokenStore(tokenStore());
}
@豆子
公共令牌库令牌库(){
返回新的JwtTokenStore(jwtAccessTokenConverter());
}
@豆子
公共JwtAccessTokenConverter JwtAccessTokenConverter(){
MyJwtAccessTokenConverter=新的MyJwtAccessTokenConverter(JWTAESEEncryptionKey);
converter.setVerifierKey(公钥);
回流转换器;
}
@豆子
@配置文件(值={“本地”})
CorsConfiguration源CorsConfiguration源(){
CorsConfiguration配置=新的CorsConfiguration();
configuration.setAllowedOriginates(Arrays.asList(“http://localhost:4200"));
setAllowedHeader(Arrays.asList(“授权”、“内容类型”));
setAllowedMethods(Arrays.asList(“GET”、“POST”));
UrlBasedCorsConfigurationSource=新的UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration(“/**”,配置);
返回源;
}
@豆子
public WebResponseExceptionTranslator oauth2ResponseExceptionTranslator(){
返回新的DefaultWebResponseExceptionTranslator(){
@凌驾
公共响应性翻译(异常e)引发异常{
试一试{
log.info(“Oauth2ExceptionTranslatorConfiguration”,e);
ResponseEntity ResponseEntity=super.translate(e);
OAuth2Exception oAuth2ExceptionBody=responseEntity.getBody();
HttpStatus statusCode=responseEntity.getStatusCode();
OAuth2Exception myOAuth2Response=OAuth2Exception.create(oAuth2ExceptionBody.getOAuth2ErrorCode(),getMessage(oAuth2ExceptionBody));
myOAuth2Response.addAdditionalInformation(“message”,myOAuth2Response.getMessage());
MyAuth2Response.addAdditionalInformation(“isSuccess”、“false”);
HttpHeaders=新的HttpHeaders();
setAll(responseEntity.getHeaders().toSingleValueMap());
返回新的ResponseEntity(MyAuth2Response、Header、statusCode);
}捕获(例外情况除外){
log.info(“Oauth2ExceptionTranslatorConfiguration”,例如);
返回新的ResponseEntity(新的OAuth2Exception(“错误”),null,HttpStatus.INTERNAL_SERVER_Error);
}
}
};
}
私有字符串getMessage(OAuth2Exception OAuth2Exception){
if(oAuth2Exception instanceof InvalidTokenException){
返回“无效令牌”;
}else if(oAuth2Exception instanceof InvalidGrantException){
返回“无效用户名或密码”;
}else if(oAuth2Exception instanceof InvalidRequestException){
返回“无效请求”;
}
返回oAuth2E
public class CustomJwtAccessTokenConverter extends JwtAccessTokenConverter {

        @Override
        protected Map<String, Object> decode(String token) {
            Map<String, Object> pieces = null;
    
            try {
               //
            } catch(InvalidTokenException ex) {
                throw new InvalidTokenException("MY CUSTOM MESSAGE");
            }
    
          //
        }
    }
@ControllerAdvice
public class MyExceptionHandler extends ResponseEntityExceptionHandler {

  @ResponseStatus(value = HttpStatus.BAD_REQUEST)
  @ExceptionHandler({HttpMessageNotReadableException.class, MethodArgumentNotValidException.class,
      HttpRequestMethodNotSupportedException.class})
  public ResponseEntity<Object> InvalidTokenException(HttpServletRequest req, Exception exception) {
    // log you request and your response
  }
}