return after call doFilter() of GenericFilterBean on Spring Boot - spring-boot

I am using GenericFilterBean as filter on my Spring boot project.
In some case, I want to pass next filter on my filter logic.
My filter looks like below;
public class MyFilter extends GenericFilterBean {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
if (anyCondition){
chain.doFilter();
return;
}
if (anyCondition){
chain.doFilter();
return;
}
if (anyCondition){
chain.doFilter();
return;
}
chain.doFilter();
}
}
it calls other chain.doFilter() if I don’t return, that’s way I return.
İt will caused any problem to return after call chain.doFilter() ?
Is it right way to handle this situations?

Your code will always call chain.doFilter (not doChain)
for example
public class MyFilter extends GenericFilterBean {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
//this gets executed before other filters
some code here
//now we execute other filters
chain.doFilter(request, response);
//this code gets executed after the 'next' filters are done
some code here
}
}
But your code always executes the next filter and then is complete.
Your code is fine, but you can do it with an if then else statement instead
public class MyFilter extends GenericFilterBean {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
if (condition1){
//do something for condition1
} else if (condition2) {
//do something for condition2
} else if (condition3) {
//do something for condition3
}
chain.doChain();
}
}

Related

How to allow swagger ui in Spring Custom Filter along with validation

I have written the following code where I have created a Custom Filter in SpringBoot which is always passed as Request Header. Request header name licenseKey and some value. I have implemented and also allowed Swagger-UI to work. Please suggest me to follow better approach, my seniors say that it is not a good approach. I provide below the code. The task is to receive licenseKey while calling Rest end point and also we need to allow Swagger-UI without licenseKey that will be provided later as part of authorization in Swagger. Currently the code is working fine. I request for better approach. I provide below the code. I removed all import statements.
#Component
public class CustomURLFilter implements Filter {
#Autowired
private CustomUserDetailsService userDetailsService;
private static final Logger LOGGER = LoggerFactory.getLogger(CustomURLFilter.class);
#Override
public void init(FilterConfig filterConfig) throws ServletException {
LOGGER.info("########## Initiating CustomURLFilter filter ##########");
}
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
String path = request.getRequestURI();
System.out.println("Path: "+path);
if(path.startsWith("/app-name-service/swagger-ui") || path.startsWith("/app-name-service/v3/api-docs")) {
filterChain.doFilter(request, response);
return;
} else {
String licenseKey = userDetailsService.getLicenseKey(request);
System.out.println("User License Key: "+licenseKey);
}
LOGGER.info("This Filter is only called when request is mapped for /customer resource");
//call next filter in the filter chain
filterChain.doFilter(request, response);
}
#Override
public void destroy() {
}
}

Onboarding filter in Spring Boot and Spring Security

I'm trying to create a filter in order to redirect logged users to the onboarding page in case they haven't completed the process before.
This is my filter so far:
#Component
#Order(110)
public class OnboardingFilter implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// cast the request and response to HTTP
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
HttpSession session = httpRequest.getSession(false);
SecurityContextImpl securityContext = (SecurityContextImpl) session.getAttribute("SPRING_SECURITY_CONTEXT");
// if there's a logged user
if (securityContext != null) {
UserPrincipal principal = (UserPrincipal) securityContext.getAuthentication().getPrincipal();
if (!principal.hasOnboarded()) {
httpResponse.sendRedirect("/onboarding");
}
}
// continue with the filter chain
chain.doFilter(httpRequest, httpResponse);
}
I've tried different values for #Order but in every case the http response generates a downloadable content instead of showing the actual requested URL or sending the redirect. Any ideas?
I'm getting this exception:
Caused by: java.lang.IllegalStateException: Committed
at org.eclipse.jetty.server.HttpChannel.resetBuffer(HttpChannel.java:917)
HttpChannel.java:917
at org.eclipse.jetty.server.HttpOutput.resetBuffer(HttpOutput.java:1423)
HttpOutput.java:1423
at org.eclipse.jetty.server.Response.resetBuffer(Response.java:1182)
Response.java:1182
at org.eclipse.jetty.server.Response.sendRedirect(Response.java:534)
Response.java:534
at org.eclipse.jetty.server.Response.sendRedirect(Response.java:543)
Response.java:543
at javax.servlet.http.HttpServletResponseWrapper.sendRedirect(HttpServletResponseWrapper.java:130)
HttpServletResponseWrapper.java:130
at org.springframework.security.web.firewall.FirewalledResponse.sendRedirect(FirewalledResponse.java:43)
FirewalledResponse.java:43
at javax.servlet.http.HttpServletResponseWrapper.sendRedirect(HttpServletResponseWrapper.java:130)
HttpServletResponseWrapper.java:130
at org.springframework.security.web.util.OnCommittedResponseWrapper.sendRedirect(OnCommittedResponseWrapper.java:135)
OnCommittedResponseWrapper.java:135
at javax.servlet.http.HttpServletResponseWrapper.sendRedirect(HttpServletResponseWrapper.java:130)
HttpServletResponseWrapper.java:130
at org.springframework.security.web.util.OnCommittedResponseWrapper.sendRedirect(OnCommittedResponseWrapper.java:135)
OnCommittedResponseWrapper.java:135
at javax.servlet.http.HttpServletResponseWrapper.sendRedirect(HttpServletResponseWrapper.java:130)
HttpServletResponseWrapper.java:130
at org.springframework.web.servlet.view.RedirectView.sendRedirect(RedirectView.java:627)
RedirectView.java:627
at org.springframework.web.servlet.view.RedirectView.renderMergedOutputModel(RedirectView.java:314)
RedirectView.java:314
at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:316)
AbstractView.java:316
at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1373)
DispatcherServlet.java:1373
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1118)
DispatcherServlet.java:1118
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1057)
DispatcherServlet.java:1057
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
DispatcherServlet.java:943
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
FrameworkServlet.java:1006
... 94 common frames omitted
What about adding a return in:
httpResponse.sendRedirect("/onboarding");
return;
Otherwise you are continuing with the filter chain:
chain.doFilter(httpRequest, httpResponse);
Not 100% sure if this is already solving your issue, but might be also a problem.
I finally solved this by implementing an Spring context-aware GenericFilterBean as follows:
public class OnboardingFilter extends GenericFilterBean {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
if (SecurityContextHolder.getContext().getAuthentication() != null) {
// some business logic
httpResponse.sendRedirect("/onboarding");
}
else {
chain.doFilter(httpRequest, httpResponse);
}
}
}
Don't forget to add it to the security filter chain:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterAfter(new OnboardingFilter(), UsernamePasswordAuthenticationFilter.class)...

Set cookie in every request - SPRING

Im now developing simple spring boot web app..
Is there something in spring(filter) that check every request(headers)..
I want to check if there is cookie..
If there is cookie- nothing happend..
But if there is not it would create cookie...
Do i have to do this manually, so i put this in every function?
Or can i do something like global function, that got executed with every other request?
Thanks for help.
yes you have to use filters
you can try doing something like this
public class MyCookieFilter extends GenericFilterBean {
public static final String MY_COOKIE_NAME = "your-cookie-name";
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
checkCookie(httpServletRequest, httpServletResponse);
filterChain.doFilter(servletRequest, servletResponse);
}
private void checkCookie(HttpServletRequest request, HttpServletResponse servletResponse) {
boolean cookieExists = Arrays.stream(request.getCookies()).anyMatch(cookie -> cookie.getName().equalsIgnoreCase(MY_COOKIE_NAME));
if (!cookieExists) {
String cookieValue = "your-cookie-value";
Cookie newCookie = new Cookie(MY_COOKIE_NAME, cookieValue);
servletResponse.addCookie(newCookie);
}
}
}
then add it in your security config
#Override
public void configure(HttpSecurity http) throws Exception {
http
...
.addFilter(new MyCookieFilter())
...
}

get request header in a Filter

I registered a Filter in Spring boot and been trying to get and Header from the request but getting null.
#Component
#Order(1)
public class ExampleFilter implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws... {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
//null**
final String header = httpServletRequest.getHeader(HEADER);
}
BUT
#GetMapping(value = "example")
public ResponseEntity<Example> example( #RequestHeader(HEADER) String header) {
... the header is NOT null
}
Please check my example here
#Component
#Order(Ordered.HIGHEST_PRECEDENCE)
public class CustomFilter implements Filter {
public CustomFilter() {
}
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
HttpServletRequest httpRequest = (HttpServletRequest) request;
Enumeration<String> headerNames = httpRequest.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
System.out.println("Header: " + name + " value:" + httpRequest.getHeader(name));
}
}
chain.doFilter(req, res);
}
#Override
public void init(FilterConfig filterConfig) {
}
#Override
public void destroy() {
}
}

Gzip filter with Spring async

I am using the new Servlet 3 feature DefferedResult in my Spring-MVC application. I had a GZIP filter which I had to remove as DefferedResult did not work with it.
Can someone tell me if there is a GZipFilter that will work with the Spring async(DefferedResult)?
Try using the filter introduced in servlet 3 - asyncSupported
#WebFilter(servletNames = { "servletAsynFilter" }, asyncSupported=true)
public class Filter1 implements Filter {
public void init(FilterConfig fConfig) throws ServletException {}
public void destroy() {}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletResponseWrapper respWrap = new HttpServletResponseWrapper((HttpServletResponse)response);
chain.doFilter(request, respWrap);
}
}

Resources