Spring Security Filter and Posted Data - spring

I wrote a custom Spring Security filter that needs to user XML data that was posted to it. How would the filter get the posted data?

It's not a really Spring Security-specific problem, since you are likely just implementing the javax.servlet.Filter interface. In this case, you are implementing the method:
public void doFilter ( ServletRequest request, ServletResponse response,
FilterChain chain ) throws IOException, ServletException;
You can then cast the ServletRequest to a HttpServletRequest if you need HTTP-specific data (which is usually required):
import javax.servlet.http.HttpServletRequest;
// ...
HttpServletRequest httpRequest = (HttpServletRequest) request;
String xml = httpRequest.getParameter("xml");
If you are extending one of the standard Spring Security filters, make sure you look at the source for the filter you're extending! Many of them already override doFilter and expect that you will override another method to augment their behavior.

Read through the documentation for AbstractAuthenticationProcessingFilter (based on your earlier question, I guess this is the class that your custom filter extends), the abstract method to implement is attemptAuthentication, which receives HttpServletRequest and HttpServletResponse as parameters:
Parameters:
request - from which to extract parameters and perform the authentication
response - the response, which may be needed if the implementation has to do a redirect as part of a multi-stage authentication process (such as OpenID).

Related

What's the most immediate way to just proxy a http request via a filter/interceptor?

For my project I need to implement a simple proxy in spring boot by using either a filter or an interceptor. So, my microservice A will just receive a http request meant for microservice B, will forward it with all headers/query params, and return the response either good or bad with the proper response code and any response header microservice B will add.
I know there are ready to use libraries like spring-cloud-gateway or spring-cloud-zuul but they both conflict with other specifications I have and cannot use them. Moreover I don't really need any filtering/aggregation logic, I just want to make a simple proxy.
I tried doing the following:
#Component
#Order(1)
public class ByPassFilter extends OncePerRequestFilter {
#Value("${proxy.active}")
private Boolean active;
#Override
public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) {
if(active){
RestTemplate rest = new RestTemplate(); //overkill here?
HttpMethod method = HttpMethod.resolve(request.getMethod());
switch(method){
case GET:
//use rest template to do get
}
}else{
filterChain.doFilter(request, response);
}
}
But RestTemplate seems very complicated as it is supposed to be used when I want to handle/process the request, it will even return exception if the code is not 200. I also have no idea on how to write the output directly to the HttpServletResponse.
So, is there any other way even more transparent? I saw people using apache's OkHttpClient, is that a little more generic than RestTemplate?

How to get raw JSON message from request and HTTP status code from response

I am developing a Spring Boot application. We have a requirement to store raw JSON request and HTTP response code to store in database as part of processing the request.
We are able to intercept request in a class that extends RequestBodyAdviceAdapter. This class has implemented afterBodyRead method to get body of the request. Unfortunately there is no way to get the raw JSON request in this method.
Similarly we have another class that has implemented ResponseBodyAdvice to intercept response. In beforeBodyWrite method, response status code is not available.
You can write a simple servlet filter:
#Component
public class JsonFilter implements Filter {
#Override
public void doFilter
ServletRequest request,
ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
// Log JSON request
chain.doFilter(request, response);
// Log JSON response and HTTP Status code
}
// other methods
}
Read more about filters and Spring Boot here: https://www.baeldung.com/spring-boot-add-filter

Earliest point to encrypt json payload in spring mvc application

I have an spring boot application serving restful api's.
I'd like to make sure that certain fields are masked / encrypted at the earliest possible time so that they are not shown in clear text in the application log ... via logback.
Is there an entry point / filter / sprint aspect I can implement so a to achieve this ?
As cearly explained in Ali Dehghani's Answer in this post the best place to do what you want to, is in a Response filter. So you have to write a class that implements the Filter interface and you filter your response in the doFilter method.
#Component
public class YourResponseFilter implements Filter {
#Override
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain) throws IOException, ServletException {
...
// do your work there
}
}
You may or may not use the annotate your filter with #Component, depending in the fact if you want to filter all your reponses or not.
If you need more help let me know.

configuring interceptors to perform "pre-tasks" on hitting endpoints in spring based web app

I am required to perform some pre-task whenever few specific endpoints are hit in my spring based web app. I came across the interceptor component provided by the spring-security framework. I searched various forums but didn't find relevant answers for configuring and adding interceptor.
Consider a situation where I am required to set some key=value in a database by sending POST request in the database whenever the user hits following endpoints.
/endpoint1
/endpoint2
/endpoint3
/endpoint4
After completion of the pre-task user should be redirected to the origin endpoint.
How can this be achieved using an interceptor in the spring-security framework?
Spring Security is for security stuff related to Authentification and Authorization. You can trigger some action if somebody logged in, but if you just need to trigger action for each request than Spring Security is not a good place for that (according to business logic), better add just filter. Anyway answering to your question:
The best way is to add custom filter to Spring Security Filter Chain:
You have to overwrite:
#Configuration
public class CustomWebSecurityConfigurerAdapter
extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterAfter(
new CustomFilter(), BasicAuthenticationFilter.class);
}
}
and create your custom filter:
public class CustomFilter extends GenericFilterBean {
#Override
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain) throws IOException, ServletException {
//your logic here
chain.doFilter(request, response); //it's needed to pass your request father
}
}
Code taken from baeldung.com see for more information

Logging all request and response in Spring Boot REST service

I use Spring boot and have some REST controllers. I want to logging all request and response. I using external tomacat, not embeded! I write Interceptor:
#Component
#Log4j2
public class LoggingWebMvcInterceptor implements HandlerInterceptor {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
final ContentCachingRequestWrapper wrapper = new ContentCachingRequestWrapper(request);
log.debug("REQ!!!! {}", wrapper.getReader().lines().collect(Collectors.joining(System.lineSeparator())));
return true;
}
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
//log.debug("Response: {}", response);
}
And adding his:
#Configuration
public class WebMvcConfig implements WebMvcConfigurer {
private final LoggingWebMvcInterceptor loggingWebMvcInterceptor;
#Autowired
public WebMvcConfig(LoggingWebMvcInterceptor loggingWebMvcInterceptor) {
this.loggingWebMvcInterceptor = loggingWebMvcInterceptor;
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loggingWebMvcInterceptor);
}
}
But It don't work!
When I try POST request, his logging, but I have error: "Required request body is missing.
What am I doing wrong? I created a wrapper for the request!
I need to completely log all requests (POST, GET, DELETE, PUT) with headers and body and all responses. How can i do this? Any help, please.
Although your problem is not every well understood (not documented well -- for example where this is coming from is not shown Required request body is missing.) but anyways.
For logging purposes, I would not go with an Interceptor as I feel that this is too much work. Instead you could very well create an Aspect with a pointcut defined to around methods annotated with the various Spring controller annotation. The ProceedingJoinPoint#proceed method effectively allows you to grab the response object and the request itself contains all the information needed regarding parameters, IP, methods and so on.
With that in hand, you could then inject a HttpServletRequest in there, thus ending up having all the right tools to perform any logging activities.
Adding the caching wrapper is something very correct indeed if you would like to cache and re-read the HttpServletRequest's body multiple time but I would avoid adding it in the Interceptor/Aspect itself.
According to Baeldung documentation, ContentCachingRequestWrapper class has these limitations:
ContentCachingRequestWrapper class only supports the following:
Content-Type:application/x-www-form-urlencoded
Method-Type:POST
and
We must invoke the following method to ensure that request data is cached in ContentCachingRequestWrapper before using it: requestCacheWrapperObject.getParameterMap();
https://www.baeldung.com/spring-http-logging
You can use a web Filter (javax.servlet.Filter) as :
public class CustomFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain){
//Log actions heres
chain.doFilter(req, resp);}}
Then declare your filter in web.xml as :
<filter>
<filter-name>MyFilter</filter-name>
<filter-class>package.CustomFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

Resources