Spring 即使OAuth2验证失败,如何记录http请求/响应正文?
我需要将Spring Boot MVC应用程序的每个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
请求
和响应
主体索引(记录)到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
}
}