I'm creating a servlet filter for my service and it seems like init() is not being called based on the logs.
I don't have a web.xml file, rather I added a #Provider annotation to the filter class.
#Provider
#WebFilter("/*")
public class TestFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {
log.debug("Test filter has been initialized");
}
#Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HeaderMapRequestWrapper requestWrapper = new HeaderMapRequestWrapper(req);
String remote_addr = request.getRemoteAddr();
requestWrapper.addHeader("remote_addr", remote_addr);
chain.doFilter(requestWrapper, response); // Goes to default servlet.
}
#Override public void destroy() { }
}
Also added to my module:
#Provides
#Singleton
public void getTestFilter() {
return new TestFilter()
}
Looks at the logs, it seems like the init() is never called. Any ideas why?
Related
the filter is always checking for authentication for the login page and I don't know how to configure it.
here is the AppFilter.java (I couldn't post all the code):
#Singleton
public class AppFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {
try {
final String appLocale = AppSettings.get().get(AvailableAppSettings.APPLICATION_LOCALE, null);
APP_LOCALE = appLocale == null ? null : new Locale(appLocale);
} catch (Exception e) {
}
}
public static String getBaseURL() {
return BASE_URL.get();
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
BASE_URL.set(computeBaseUrl(request));
LANGUAGE.set(request.getLocale());
try {
chain.doFilter(request, response);
} finally {
LANGUAGE.remove();
BASE_URL.remove();
}
}
}
You can modify doFilter() in order to check if the requested URL belongs to the list of predefined excluded URLs, if so then just forward the request to the next filter or servlet in the chain, otherwise do whatever you want to do.
Here is the code:
#Singleton
public class AppFilter implements Filter {
private List<String> excludedUrls;
#Override
public void init(FilterConfig filterConfig) throws ServletException {
excludedUrls = Arrays.asList(YOUR_LOGIN_URL);
Filter.super.init(filterConfig);
}
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
String path = ((HttpServletRequest) servletRequest).getServletPath();
if(!excludedUrls.contains(path))
{
// if url does not match your login url do what you want to do..
}
// else forward the request to the next filter or servlet in the chain.
chain.doFilter(req, resp);
}
#Override
public void destroy() {
}
}
I want to Authenticate one of the post request body key-value pair, but I want to do the same with the help of a Interceptor/Filter. How can I do that?
You can create a custom request filter that will check the request:
public class MyFilter implements OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) {
var user = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
// do stuff you need to do here
filterChain.doFilter(request, response);
}
}
and then in your WebSecurityConfiguration class register the filter like this
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterAfter(new MyFilter(), BasicAuthenticationFilter.class);
}
}
You can extend HandlerInterceptorAdapter and perform your custom operations/filters on top of request by overriding preHandle() method.
Pseudocode is here:
#Component
public class SimpleInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// Handle your request here. In your case, authentication check should go here.
return true;
}
}
Add the SimpleInterceptor to the registry to intercept the requests.
#Configuration
#EnableWebMvc
public class SimpleMvnConfigurer implements WebMvcConfigurer {
#Autowired
SimpleInterceptor simpleInterceptor;
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(simpleInterceptor);
}
}
That's all!
EDIT 1:
To send the response from preHandle method, follow below pseudocode:
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// Handle your request here. AIn your case, authentication check should go here.
if (!isValidAuth()) {
// Populate the response here.
try {
response.setStatus(401);
response.getWriter().write("Authentication failed.");
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
return true;
} ```
You can try this with Filter.
public class SimpleFilter implements Filter {
private void throwUnauthorized(ServletResponse res) throws IOException {
HttpServletResponse response = (HttpServletResponse) res;
response.reset();
response.setHeader("Content-Type", "application/json;charset=UTF-8");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
if (!isValidAuth(request)) {
throwUnauthorized(res);
}
chain.doFilter(req, res);
}
private boolean isValidAuth(HttpServletRequest request) {
// YOUR LOGIC GOES HERE.
return false;
}
#Override
public void destroy() {
}
#Override
public void init(FilterConfig arg0) {
}
}
Register the filter using FilterRegistrationBean
#Bean
public FilterRegistrationBean<SimpleFilter> simpleFilter() {
FilterRegistrationBean<SimpleFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new SimpleFilter());
return registrationBean;
}
Let me know if this works.
I was working on a project where based on the presence of a particular string in the request URL to a web application, I was trying to modify the URL of the request using a request wrapper.
I learnt that even if I override the getRequestURI, getRequestURL and getServletPath methods in the wrapper and send that wrapper from a filter, the servlet container still uses its own implementation of the ServletRequest interface to figure out which servlet to call.
I believe the container uses the stored variable for the request URI in the implementation class of ServletRequest and doesn't actually call any of the getRequestURI, getRequestURL and getServletPath methods for identifying the servlet to use (matching URL pattern).
Need all your inputs and knowledge to learn more about this topic. Please help me learn this topic better. Thanks..!!
Below are my experimental code and the request comes from the jsp for http://localhost:8080/RequestResponseListenersWebApp/pages/abcd.jsp
The Filter
#WebFilter(filterName = "AllRequestScanFilter", urlPatterns = "/*")
public class AllRequestScanFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
EmployerViewTestBusinessWrapper wrapper = new EmployerViewTestBusinessWrapper(request);
if (request.getRequestURI().contains("abcd.jsp"))
chain.doFilter(wrapper, resp);
else {
chain.doFilter(req, resp);
}
}
public void init(FilterConfig config) throws ServletException {
}
}
The Wrapper
public class EmployerViewTestBusinessWrapper extends HttpServletRequestWrapper {
public EmployerViewTestBusinessWrapper(HttpServletRequest request) {
super(request);
}
#Override
public String getPathTranslated() {
return super.getPathTranslated();
}
#Override
public String getRequestURI() {
String currentPath=pathModified(super.getRequestURI());
return currentPath!=null?currentPath:super.getRequestURI();
}
#Override
public StringBuffer getRequestURL() {
String currentPath=pathModified(super.getRequestURL().toString());
return currentPath!=null?new StringBuffer(currentPath):new StringBuffer(super.getRequestURL());
}
#Override
public String getServletPath() {
String currentPath=pathModified(super.getServletPath());
return currentPath!=null?currentPath:super.getServletPath();
}
private String pathModified(String currentPath){
String returnPath=null;
if(currentPath.contains("pages")){
returnPath=currentPath.replaceFirst("/pages/","/pages/myapp/");
}
return returnPath;
}
}
The Servlet which is never reached
#WebServlet(name = "EmployerViewTestServlet",urlPatterns = "/pages/myapp/*")
public class EmployerViewTestServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String path=request.getParameter("path");
}
}
And one more thing. The Filter I have specified here is the first thing in the web app that's called when a request comes in.
I can always check the URL pattern in the filter and forward the request to the desired URL pattern using a RequestDispatcher.
However, in my app there're some Filters that are called for dispatcher type FORWARD and I don't want them to be called when a request has just come from the client.
Wouldn't be this what you're looking for?
In that case, the request.getRequestDispatcher(newURI).forward(req, res) seems to do the trick, using only the filter.
#WebFilter(filterName = "AllRequestScanFilter", urlPatterns = "/*")
public class AllRequestScanFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
//EmployerViewTestBusinessWrapper wrapper = new EmployerViewTestBusinessWrapper(request);
String URI = request.getRequestURI();
if (URI.contains("abcd.jsp") && URI.contains("pages")) {
URI = URI.replaceFirst("/pages/","/pages/myapp/");
request.getRequestDispatcher(URI).forward(req, res);
} else {
chain.doFilter(req, resp);
}
}
public void init(FilterConfig config) throws ServletException {
}
}
I made a simple servlet filter to slow the responses of my app down:
import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class DelayFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {}
#Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
Integer seconds = 10;
try {
Thread.sleep(seconds * 1000);
} catch (InterruptedException e) {
throw new ServletException("Interrupted!");
}
HttpServletResponse response = (HttpServletResponse) resp;
response.setHeader("Cache-Control", "no-cache, must-revalidate");
chain.doFilter(req, resp);
}
#Override
public void destroy() {}
}
I read a bunch of articles to register it for the app like this: enter link description here
Usually there are two methods of registering, one for using web.xml and one for programmatic configuration. The Application I have to work with doesn't use the XML, but neither have any initializer class. Configuration ist done with a Config Class starting like this:
#Configuration
#EnableWebMvc
#EnableAsync
#EnableTransactionManagement
#EnableSpringConfigured
#PropertySource("classpath:config/application.properties")
public class ApplicationConfiguration extends WebMvcConfigurerAdapter {
So I made an initializer
import javax.servlet.Filter;
public class arachneInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses () {
return null;
}
#Override
protected Class<?>[] getServletConfigClasses () {
return new Class<?>[]{ApplicationConfiguration.class};
}
#Override
protected String[] getServletMappings () {
return new String[]{"/"};
}
#Override
protected Filter[] getServletFilters() {
return new Filter[] {
new DelayFilter()
};
}
}
I am not sure, if this is correct or will it change they way my Application acts? Everything seems to be normal at a first glance though.
But the filter does not kick in! Any ideas what I did wrong or suggestion how I can add the filter maybe without an Initializer?
Edit: I use Spring MVC 4.3.4.
The #WebFilter annotation is used to declare a filter in a web application.So the servlet container will process your filter at deployment time and will associate to the specified URL in our case (/*)
Before that you should do it in the web.xml
#WebFilter(urlPatterns = {"/*"}, description = "My delay filter ")
public class DelayFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {}
#Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
Integer seconds = 10;
try {
Thread.sleep(seconds * 1000);
} catch (InterruptedException e) {
throw new ServletException("Interrupted!");
}
HttpServletResponse response = (HttpServletResponse) resp;
response.setHeader("Cache-Control", "no-cache, must-revalidate");
chain.doFilter(req, resp);
}
#Override
public void destroy() {}
}
There are several programmatic ways to register a filter using Spring MVC. You can check this answer.
I'd like to run some code (for logging, or custom security, etc) before and/or after spring calls the controller method. I know Filters can be created to operate on ServletRequests and ServletResponses, but it's not clear how to access headers, body, query parameters, etc from those.
Most similar to what I'm trying to do is action composition in Play Framework for java.
Is there a way to do this in Spring?
Here is an example of how to inject a Header for every request using a Filter
#Component
#Order(Ordered.HIGHEST_PRECEDENCE)
public final class VersionFilter implements Filter {
#Value("${version}")
protected String version;
protected FilterConfig filterConfig;
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletResponse responseAddition = (HttpServletResponse) response;
responseAddition.addHeader("X-Application-Version", this.version);
chain.doFilter(request,responseAddition);
}
#Override
public void destroy() {
}
}