Spring boot: Serving public and private (restricted) static content - java

I'm using spring-boot-starter-web along with embedded-jetty and starter-jersey starter. The Jersey servlet context-path is configured in application.properties to serve from /api. So all /api/.* calls are handled over to Jersey.
Since I'm using starter-web, the static content is being served from static/ directory as shown here:
All the resources listed under static/public/ can be accessed without any restrictions. But the resources under static/private should be restricted and will be shown only if logged in.
To achieve this, I've written a filter:
#Component
#Order(1)
public static class PrivateContentFilter implements Filter {
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
if (request.getRequestURI().matches(".*/static/private/.*")) {
// Check for authentication in the cookie and procceed
// The cookie is handed to an auth mirco-service, that does the actual validation.
}
}
}
But this filter is only reached when the path is api/.* and not for the static content: /public/.* nor for /private.*. What am I missing here?

Everything that is under /static is the context / so your filter regex must look like this:
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
if (request.getRequestURI().matches("/private/.*")) {
System.out.println("private");
} else {
System.out.println("public");
}
filterChain.doFilter(servletRequest, servletResponse);
}

Related

How can we get the entity from HttpServletResponse?

The context is I want to migrate my Jersey Application to Spring MVC, For the Filter part, Jersey ContainerRequestContext has getEntity() function, which I can use to check response type is MyClientResponse or not
#Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) {
if (isMyClientResponse(responseContext.getEntity())) {}
but in spring Filter
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
the param HttpServletResponse doesn't have such method which I can extract the entity object from it
In Java HttpServletResponse class, I only see method like
public ServletOutputStream getOutputStream() throws IOException;
but don't see method like
public Object getEntity();
Which we can get the entity body from it, so how can we get entity from HttpServletResponse? Or is there any way to convert ServletOutputStream to Object?

ClickjackingPreventionFilter in jsp: #WebFilter vs CustomFilter

So in jsp i'm trying to prevent Clickjacking,
#WebFilter(urlPatterns = "/*", initParams = #WebInitParam(name="mode", value="SAMEORIGIN"))
public class ClickjackingPreventionFilter implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse)response;
res.addHeader("X-FRAME-OPTIONS", "SMAEORIGIN" );
chain.doFilter(request, response);
}
}
Ppl suggested to use custom filter instead of WebFilter.
https://www.baeldung.com/spring-security-custom-filter
I'm trying to understand the difference.
To my little understanding, WebFilter is a standard filter, i just need to pass parameters.
Vs custom filter is a "custom" filter as its name says.
Any comments on which way i should go ? Thx !

is there a way to implement the X-Robots-Tag instruction with tomcat?

I want to add X-Robots-Tag noindex, nofollow to the HTTP response of all the .PDF files of a site to avoid that these documents be referenced by the Google search engine.
This is for Tomcat 8 server on Heroku with Spring boot 2.1. From the past, I've tried on Apache Server and the noindex and nofollow worked well.
<Files ~ "\.pdf$">
Header set X-Robots-Tag "noindex, nofollow"
</Files>
You could create a servlet filter that does this for you like.
#WebFilter(urlPatterns = {"*.pdf"})
public class PdfFilter implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse httpServletResponse = (HttpServletResponse)response;
httpServletResponse.addHeader("X-Robots-Tag", ""noindex, nofollow");
chain.doFilter(request, response);
}
}

cant able to get proper responses in dofilter method?

I have defined servlet filter implementation in spring boot application. I could get only 200 response for all calls. How to get the appropriate response in dofilter method?
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
doFilterFunction.requestFunction(request, response, chain);
}
public void requestFunction(ServletRequest request, ServletResponse response, FilterChain chain,String x_internal_key, String session, String user, String urlPat) throws IOException, ServletException {
chain.doFilter(request, response);
}
I had removed try catch block to get the entire responses from servlet.Its working fine.

Spring boot HandlerInterceptor loadbalancing

I'm implementing a (sort of) load balancing HandlerInterceptor using Spring Boot.
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String uri = request.getRequestURI();
if (shouldUseServer1(uri)) {
response.sendRedirect(server1Uri);
} else {
response.sendRedirect(server2Uri);
}
}
The idea is, that based on the url, we either redirect to one service or another. The application doesn't have any explicit RequestMappings (yet).
Now the problem is, when the interceptor is called, the request is redirected to the default Spring error handler. As a result the URI stored in the HttpServletRequest is replaced by /error (effectively denying the access to the original URI).
Is there any way to intercept a request before it is rerouted to the error handler (or to get the original uri)?
EDIT:
Because of the way Spring MVC handles requests with no mapping, you'll either need a filter:
#Component
public class CustomFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
request.getSession().setAttribute("ORIGINAL_REQUEST_URI", request.getRequestURI());
chain.doFilter(request, response);
// alternatively, ignore the last 2 lines
// and just do your redirects from here
// and don't continue the filter chain
}
#Override
public void destroy() {}
#Override
public void init(FilterConfig arg0) throws ServletException {}
}
Otherwise, if you'd rather not rely on the session, you'll need to make the DispatcherServlet throw an exception in case no handler mapping is found, and then send the redirect from a #ControllerAdvice error handler:
#ControllerAdvice
class NoHandlerFoundExceptionExceptionHandler {
#ExceptionHandler(value = NoHandlerFoundException.class)
public ModelAndView
defaultErrorHandler(HttpServletRequest req, NoHandlerFoundException e) throws Exception {
String uri = // resolve the URI
return new ModelAndView("redirect:" + uri);
}
}
To avoid duplication, you may want to have a common class that you'll call from both the interceptor and the error handler.

Categories