ClickjackingPreventionFilter in jsp: #WebFilter vs CustomFilter - java

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 !

Related

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

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);
}

How can I unit test mith Mockito my Filter that change Character response and request encoding?

I have filter that sets character encoding.How can I test It with Mockito?
My Filter:
#WebFilter(filterName = "CharacterEncodingFilter")
public class CharacterEncodingFilter implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
chain.doFilter(request, response);
}
}
Depends if you are doing a unit test you simply do the following:
#Test
public void filterSetsCharacterEncoding() {
//given
CharacterEncodingFilter filter = new CharacterEncodingFilter();
ServletRequest request = mock(ServletRequest.class);
ServletResponse response = mock(ServletRequest.class);
FilterChain chain = mock(FilterChain.class);
//when
filter.doFilter(request, response, chain);
//then
verify(request).setCharacterEncoding("UTF-8");
verify(response).setCharacterEncoding("UTF-8");
}
Basically just instantiate the filter, pass mock objects as parameters and verify that the request and response setCharacterEncoding have been called with UTF-8 parameter.
You might also want to verify that chain.doFilter was invoked. I would test that in a new method, as the above method already tests that character encoding was set.

Servlet API - Filter Response Wrapper

I am new to Servlet programming and I have a question about wrapping response. Because I couldnt understand when to use it. For example I have filter and servlet as below.
Filter
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
chain.doFilter(req, resp);
HttpServletResponse httpServletResponse = (HttpServletResponse)resp;
httpServletResponse.getWriter().println("hi from filter");
}
Servlet
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().println("Hi from servlet");
}
So , What is the difference between them ? I could use both of them to write by using same response object because there are full duplex way (Sincerely, same request and response instances goes to servlet and comes to filter again) between servlet and filter , aren't there ? I am little confused. I appriciate If you could give me a decent sceneraio that could obviously demonstrate the wrapper class's goal.
Thanks & Regards :)

how to prevent servlet from being invoked directly through browser

I was working on a web project using java servlet and jsp pages. In one of the servlet we have RequestDispatcher method and which is calling another servlet.
#WebServlet("/Demo")
public class DemoServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.sendRedirect("testing"); //calling other servlet
}
}
#WebServlet("/testing")
public class TestingServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("Hello World");
}
}
So, now I wanted to prevent contextRoot/testing from being invoked directly from the browser but instead only let it invoked from the other servlet(Demo)
Please suggest me if there is any way to do that.
Couple of techniques exist:
Look at writing a HTTP Request Filter. You can then inspect the incoming request and the url and reject it if the pattern matches the servlet paths that you do not want to be invoked directly.
Another mechanism is to use the security constraints in your web.xml to allow access to various paths in your application only to authorized users/roles. Look at <security-constraint> tag in web.xml
Answer given by "Romin" is correct. You have to use Filters for this. what you can do is, you can set a new session variable whenever "/Demo" url is accessed and in the filter check for the condition that session exists, if it exists allow the url or else throw error. You could do something similar like this. In "Demo" servlet
#WebServlet("/Demo")
public class DemoServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
HttpSession session = request.getSession() //get new session
res.sendRedirect("testing"); //calling other servlet
}
}
In Filter class add the below code
#WebFilter("/login")
public class MyFilter implements Filter{
public void init(FilterConfig arg0) throws ServletException {}
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpRequest request = (HttpRequest) req;
HttpResponse respone = (HttpResponse) res;
HttpSession session = request.getSession(false) //get the existing session object
if(null != session) {
chain.doFilter(req, resp);
} else {
"redirect to some error page or home page"
}
}
public void destroy() {}
}
One approach is to check the caller's ip using ServletRequest.getRemoteAddr() and rejects it if it's not called locally
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
if(!req.getRemoteAddr().equals("127.0.0.1")) { // reject }
}
However this method wouldn't work legitimate caller (eg: proxy) is also using the same ip.

Want to create a filter to check for a cookie, then save object and reference from controllers

I want to create a filter that will execute before any of my spring mvc controller actions.
I want to check for the existence of a cookie, and then store an object somewhere for the current request only.
I then need to reference this object (if it exists) from within my controller action.
Suggestions on how to do this?
to create the filter just make a class that implements javax.servlet.Filter, in your case can be something like this
public class CookieFilter implements Filter {
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
 
Cookie[] cookies = request.getCookies();
if (cookies != null){
for (Cookie ck : cookies) {
if ("nameOfMyCookie".equals(ck.getName())) {
// read the cookie etc, etc
// ....
// set an object in the current request
request.setAttribute("myCoolObject", myObject)
}
}
        chain.doFilter(request, res);
    }
    public void init(FilterConfig config) throws ServletException {
// some initialization code called when the filter is loaded
    }
    public void destroy() {
// executed when the filter is unloaded
    }
}
then declare the filter in your web.xml
<filter>
    <filter-name>CookieFilter</filter-name>
    <filter-class>
        my.package.CookieFilter
    </filter-class>
</filter>
<filter-mapping>
    <filter-name>CookieFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
at this point in your controller just check if the attibute exists in the request using request.getAttribute("myCoolObject")
The Java 8 way of doing this by using stream to filter the required cookie and then use it as per the required logic :
public class CookieFilter implements GenericFilterBean {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
Cookie[] cookies = request.getCookies();
Stream<Cookie> stream = Objects.nonNull(cookies) ? Arrays.stream(cookies) : Stream.empty();
String cookieValue = stream.filter(cookie -> "nameOfMyCookie".equals(cookie.getName()))
.findFirst()
.orElse(new Cookie("nameOfMyCookie", null))
.getValue();
if (Objects.nonNull(cookieValue)) {
request.setAttribute("myCoolObject", myObject);
}
chain.doFilter(request, res);
}

Categories