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

     2023-02-27     82

关键词:

【中文标题】即使 OAuth2 验证失败,如何记录 http 请求/响应正文?【英文标题】:How to log http request/response body even if OAuth2 validation failed? 【发布时间】:2021-01-12 13:34:04 【问题描述】:

我需要将 Spring Boot MVC 应用程序的每个 requestresponse 正文索引(记录)到 Elasticsearch 应用程序中。我在过滤器中实现了日志记录,使其具有最高优先级(顺序 1)。

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

public class MyJwtAccessTokenConverter extends JwtAccessTokenConverter 
                @Override
                protected Map<String, Object> decode(String token) 
                   //logic to throw token error
           
   

即使令牌未经过验证,我也想为请求和响应正文编制索引。我该怎么做?有没有办法在令牌验证之前放置过滤器或任何其他记录请求和响应的特定方式?

编辑: 我的 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();
    


【问题讨论】:

您是否尝试在 jwt 授权过滤器之前添加您的过滤器?就像资源服务器配置中的 http.....addFilterBefore(yourcustomfileter, JwtAuthorizationFilter.class) 一样。另外请分享您的过滤器配置 @balias 实际上我在项目中找不到JwtAuthorizationFilter 实现。该项目的实现与通常的 Spring Security 略有不同。我已经更新了 ResourceServer 配置。你能调查一下吗? 【参考方案1】:

这个想法是为此目的使用自定义异常和 ControllerAdvice

所以我的示例代码就像

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来捕捉你想要的东西

@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
  

如果需要响应,请添加 HttpServletResponse 响应

希望有用

【讨论】:

是的,这可能是解决方案,但我也想在成功的情况下登录(不仅是失败)。此外,除了 InvalidTokenException 之外,我还想记录响应可能还有其他异常。所以,我正在寻找一个常见的地方来记录请求/响应(如过滤器)。我已经更新了 ResourceServer 配置。你能调查一下吗?【参考方案2】:

我找到了一个简单的解决方案。如果我将过滤器顺序设置为HIGHEST_PRECEDENCE 并带有注释@Order(Ordered.HIGHEST_PRECEDENCE),那么它会在令牌验证之前进入(我可以在其中记录请求)并在我也可以记录响应的所有过滤器/操作之后退出。

【讨论】:

Oauth2 身份验证失败

】Oauth2身份验证失败【英文标题】:Oauth2authenticationfailed【发布时间】:2016-04-2711:30:12【问题描述】:我正在尝试在我的应用程序(客户端)中使用springOAUTH2sso,并安装了一个oauth2提供程序。在oauth2提供程序中配置客户端并在客... 查看详情

如何使用 OAuth2 身份验证设置 traefik

】如何使用OAuth2身份验证设置traefik【英文标题】:HowtosettraefikwithOAuth2authentication【发布时间】:2018-11-2201:19:40【问题描述】:我使用traefik作为反向代理。我想为入口点设置OAuth2身份验证。在文档中,我找到了ForwardAuthentication,... 查看详情

即使验证失败,Core Data 也会保存对象

】即使验证失败,CoreData也会保存对象【英文标题】:CoreDatasavesobjectevenwhenvalidationfails【发布时间】:2010-10-2220:25:31【问题描述】:我已经包含了处理所有保存功能的函数。这是我的问题。我正在抓取5个输入值并将其保存为CoreDa... 查看详情

如何在 OAuth2 WebFlux 中设置成功和失败处理程序

】如何在OAuth2WebFlux中设置成功和失败处理程序【英文标题】:HowtosetsuccessandfailurehandlersinOAuth2WebFlux【发布时间】:2020-01-1620:37:52【问题描述】:在SpringWeb(非响应式)中,我们可以为oauth2login设置成功和失败处理程序,如下所示... 查看详情

如何使用 Angular 2 进行 oAuth2 基本身份验证?

】如何使用Angular2进行oAuth2基本身份验证?【英文标题】:HowtodooAuth2Basicauthenticationwithangular2?【发布时间】:2018-02-0822:10:09【问题描述】:我正在使用角度2进行oauth2。这里是POSTURL="http://localhost:8080/OAuth2Example/oauth/token?grant_type=pass... 查看详情

如何防止 ASP.NET 记录身份验证失败?

】如何防止ASP.NET记录身份验证失败?【英文标题】:HowdoIpreventASP.NETfromloggingauthenticationfailures?【发布时间】:2014-06-0808:35:55【问题描述】:我的WindowsAzureWeb角色ASP.NETMVC应用程序在某些路由上提供RESTAPI请求,而这些路由需要“基... 查看详情

RestSharp OAuth2 承载身份验证失败,访问被拒绝

】RestSharpOAuth2承载身份验证失败,访问被拒绝【英文标题】:RestSharpOAuth2BearerAuthenticationFailingWithAccessDenied【发布时间】:2015-07-0518:55:33【问题描述】:我已经实现了我自己的自定义IAuthenticator,称为OAuth2BearerAuthenticator,它基本... 查看详情

使用 OWIN 和 JWT 时如何记录身份验证失败的原因?

】使用OWIN和JWT时如何记录身份验证失败的原因?【英文标题】:HowtologauthenticationfailurereasonswhenusingOWINandJWT?【发布时间】:2016-02-0806:59:08【问题描述】:我正在使用c#自托管OWIN服务器,并已将我的应用程序配置为使用JWT授权,如... 查看详情

邮件表单提交,即使验证失败

】邮件表单提交,即使验证失败【英文标题】:Mail-formsubmits,evenaftervalidationfail【发布时间】:2020-01-3112:24:49【问题描述】:尝试通过对提交表单进行简单的验证检查来运行此代码。错误消息弹出,但表单仍然被提交。谁能指出... 查看详情

云功能的 OAuth2 身份验证

】云功能的OAuth2身份验证【英文标题】:OAuth2authenticationforaCloudfunction【发布时间】:2021-04-2209:14:42【问题描述】:我需要从本地编写的python代码调用(OAuth-客户端凭据流和授权代码流)http云函数。我在GCP项目上创建了OAuth2.0客... 查看详情

即使 Parsley 验证失败,.submit() 也会始终执行

】即使Parsley验证失败,.submit()也会始终执行【英文标题】:.submit()isalwaysexecutedevenwhenParsleyvalidationfails【发布时间】:2018-12-2300:31:06【问题描述】:我正在使用parsley.js进行验证。它在不使用Ajax的情况下完成了这项工作。但是当... 查看详情

如何在没有基本 http 身份验证的情况下强制 MockitoJUnitRunner 失败?

】如何在没有基本http身份验证的情况下强制MockitoJUnitRunner失败?【英文标题】:HowtoenforceMockitoJUnitRunnerfailwithoutbasichttpauthentication?【发布时间】:2020-02-1212:44:47【问题描述】:我编写了一个SpringBoot应用程序,并且能够使用MockMvc... 查看详情

Spring OAuth2 禁用 TokenEndpoint 的 HTTP 基本身份验证

】SpringOAuth2禁用TokenEndpoint的HTTP基本身份验证【英文标题】:SpringOAuth2disableHTTPBasicAuthforTokenEndpoint【发布时间】:2016-11-0502:48:54【问题描述】:我从SpringOAuth2开始。到目前为止一切顺利,我已经通过配置保护了我的应用程序。但... 查看详情

禁止 (403) CSRF 验证失败。请求中止。即使使用 % csrf_token %

】禁止(403)CSRF验证失败。请求中止。即使使用%csrf_token%【英文标题】:Forbidden(403)CSRFverificationfailed.Requestaborted.Evenusingthe%csrf_token%禁止(403)CSRF验证失败。请求中止。即使使用%csrf_token%【发布时间】:2014-01-2015:26:30【问题描述】:... 查看详情

如何使用 OAuth2 身份验证保护私有数据?

】如何使用OAuth2身份验证保护私有数据?【英文标题】:HowcanprivatedatabesecuredwithOAuth2authentication?【发布时间】:2014-11-0713:18:23【问题描述】:我正在建立一个网站以使用Google的OAuth2界面进行用户身份验证。该网站将存储与每个用... 查看详情

即使设置了 cookie,RabbitMQ 身份验证也会失败

】即使设置了cookie,RabbitMQ身份验证也会失败【英文标题】:GettingRabbitMQauthenticationfailingevenwithcookieisset【发布时间】:2018-11-1811:04:27【问题描述】:我最近在lattePanda上运行的Windows10上安装了带有ErlanOTP的rabbitmq我运行rabbitmqctlstatu... 查看详情

即使通过代理连接失败,如何重试当前循环(代码片段)

所以我想要废弃一堆链接,但经常发生的是在循环中间(当试图连接到随机链接时),突然通过代理连接失败,循环停止而我的程序结束。这是代码:importrequestsfrombs4importBeautifulSoupassoup#SettingProxyproxies="http":"http://232.454.676.898:8888... 查看详情

如何使用 oauth2 通过 REST Web 服务进行身份验证

】如何使用oauth2通过RESTWeb服务进行身份验证【英文标题】:Howtoauthenticatewithrestwebserviceusingoauth2【发布时间】:2016-01-2720:20:51【问题描述】:您好,我有一个实现oauth2.0的休息网络服务。现在我的Web应用程序有一个登录名,目前... 查看详情