【发布时间】:2021-01-12 13:34:04
【问题描述】:
我需要将 Spring Boot MVC 应用程序的每个 request 和 response 正文索引(记录)到 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 配置。你能调查一下吗?
标签: spring spring-boot spring-mvc spring-security oauth-2.0