Is Spring AOP the easiest solution for crosscut logging of Http requests (inbound and outbound)? [closed] - spring

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 months ago.
Improve this question
I wanted to check to see if I hadn't missed another option for logging.
I want to be able to add logging of HTTP input requests and HTTP output requests without having to add explicit logging constructs just before/after each call. AOP seems to be a way of doing this. Is there another fashion? I was also looking at wiretap/global channel interceptors but this would not appear to apply to inbound-endpoints and outbound-endpoints. Thanks for any pointers.

You could log inbound requests and outbound responses with a javax.servlet.Filter implementing class.
#WebFilter(urlPatterns = {"/*"})
public class logFilter implements Filter {
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
System.out.println("Inbound request " + httpServletRequest.getRequestURI());
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("Outbound response " + httpServletResponse.getStatus());
}
}

Related

Spring how create filter that reads body but keeps request intact [duplicate]

This question already has answers here:
How to get request body params in spring filter?
(2 answers)
Closed 4 months ago.
I need to calculate a value for every request body (soap requests) for this i created a filter (extending OncePerRequestFilter):
#Component
#RequiredArgsConstructor
public class AddHashFilter extends OncePerRequestFilter {
private final RequestHash hash;
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
HttpServletRequest requestToUse = request;
if(!(request instanceof ContentCachingRequestWrapper)){
requestToUse = new ContentCachingRequestWrapper(request);
}
hash.hash(IOUtils.toString(requestToUse.getInputStream(), StandardCharsets.UTF_8));
filterChain.doFilter(requestToUse, response);
}
}
The problem is that this somehow destroys the request - i get 400. What i tried:
using request.geReader -> get an exception that getReader was already called
omit using ContentCachingRequestWrapper -> no change
i also tried this variant to read the body (from examples i found)
#Component
#RequiredArgsConstructor
public class AddHashFilter extends OncePerRequestFilter {
private final RequestHash hash;
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
hash.hash(new String(StreamUtils.copyToByteArray(request.getInputStream()), StandardCharsets.UTF_8));
filterChain.doFilter(request, response);
}
}
The problem is same: all request are quit with 400.
But if i remove the actual work/ use of this filter (only keeping filterChain.doFilter...) it is working.
So how can i read complete body and keep it usable for everything after?
Http request could be read only once, so if you read it in filter you can not use it again. Spring provides its own class that extends HttpServletRequest and allows reading its contents multiple times. And that resolves your problem. See this question and my answer to it: How to get request body params in spring filter?

How to log HTTP exchanges (including the payloads) in spring-boot with spring-web

Is there any way to log complete HTTP exchanges (request + response including headers + payloads) in a spring-web REST service?
I have seen the CommonsRequestLoggingFilter, but that only logs the request. Is there a matching CommonsResponseLoggingFilter? Or a different solution?
In Jersey this functionality is provided by LoggingFeature, you just need to enable it.
For the HTTP server I use the default Tomcat. There's AccessLogValve, but that doesn't log the payload.
Ideally I would want something at spring-web level, similar to Jersey, so I don't have to worry about it if I switch from Tomcat to Jetty or Undertow.
I am not sure if spring have any build-in filter which help to log both request/response.
But you can write customize filter to do it.
#Component
public class CustomLoggingFilter extends GenericFilterBean {
#Override
public void doFilter(
final ServletRequest req,
final ServletResponse res,
final FilterChain chain)
throws IOException, ServletException {
CachedBodyHttpServletRequest reqWrap = new CachedBodyHttpServletRequest(
(HttpServletRequest) req);
ContentCachingResponseWrapper resWrap = new ContentCachingResponseWrapper(
(HttpServletResponse) res);
chain.doFilter(reqWrap, resWrap);
resWrap.copyBodyToResponse();
}
}
CachedBodyHttpServletRequest and ContentCachingResponseWrapper can help you to access headers/datas multiple time and do few logging without broken any datas.
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/util/ContentCachingRequestWrapper.html
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/util/ContentCachingResponseWrapper.html

Secure spring webapp with cookies

I am writing a little service which uses websockets (not topic!). I researched on how to secure websockets. But the documentations all say I have to secure the webapp like every other webapp (i.e. basic auth). I already tried basic auth and it seems to work. But I am in the need of securing the websocket service by cookies. So my question is:
How do you secure a spring webapp by cookies?
Regards
It can be done via servlet filters.
#Service
public class MyCookieAuthenticationFilter extends GenericFilterBean {
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//set principal to request after request was validated...
}
}
You have to register the filter too.

How to authenticate a user in spring boot? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I'm not understanding how this code works especially the OncePerRequestFilter class what's the purpose of this class I''ve pasted the code available to me.
public class AuthenticationFilter extends OncePerRequestFilter{
private final LoginService loginService;
private static final Logger logger = Logger.getLogger(AuthenticationFilter.class);
public AuthenticationFilter(final LoginService loginService) {
super();
this.loginService = loginService;
}
#Override
protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response, final FilterChain filterChain)
throws ServletException, IOException {
final String xAuth = request.getHeader("X-Authorization");
Authenticate and Authorization are two different terms.
1. Authenticate : you are the one who you are claiming.
2. Authorization : What are you allowed to do.
Assumption : your question is for authorize : " I want to authorize specific user based on rest api's".
configure http.authorizeRequests().antMatchers("/products").access("hasRole('ROLE_ADMIN')")
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/products").access("hasRole('ROLE_ADMIN')").anyRequest().permitAll().and().authorizeRequests().antMatchers("/hello").access("hasRole('ROLE_ADMIN')").anyRequest().permitAll().and()
.formLogin().loginPage("/login").usernameParameter("username").passwordParameter("password").and()
.logout().logoutSuccessUrl("/login?logout").and().exceptionHandling().accessDeniedPage("/403").and()
.csrf();
}
refer for full code : https://github.com/Roshanmutha/SpringSecurityJDBC/blob/master/src/main/java/com/roshantest/WebSecurityConfig.java

Spring security & Wicket + filters

the main approach to use when securing Wicket application using Spring security is to include such construct in AuthenticatedWebSession:
Authentication authentication = authenticationManager
.authenticate(new UsernamePasswordAuthenticationToken(username, password));
SecurityContextHolder.getContext().setAuthentication(authentication);
authenticated = authentication.isAuthenticated();
In opposition to Spring Security authentication request comes within a backend so there is too late for any HTTP Request processing. That said entire Spring Security filter chain is DOWN no-matter what, see this line in the AbstractAuthenticationProcessingFilter:
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
if (!requiresAuthentication(request, response)) {
chain.doFilter(request, response);
return;
}
// (...) "normal" Spring authentication process which will never take place
successfulAuthentication(request, response, chain, authResult);
}
Where the requiresAuthentication method checks for the "j_spring_security_check" on the request path. Of course there isn't any in the approach taken.
What's the consequence? Since you rely ONLY on the AuthenticationManager you obtain from the application context itself actions that would normally be triggered in the filter chain just won't happen: for instance Spring remember-me services won't work. Cookies are being set in the filter method which returns prematurely. Cookies can be read, but they do not exist.
And my question is - is there a serious Spring Security to Wicket adaptation or not? I mean it should skip the chain but trigger all those actions which would normally be run from within the backend, as Wicket does.
Thanks!

Resources