Filter not being executed at all - servlets

I have a simple HttpServlet Filter in Tomcat 8 that I want to use on every request, and then proceed to the other servlets. But the filter is not being executed at all. Here is the web.xml
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="3.1">
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<filter>
<filter-name>requestFilter</filter-name>
<filter-class>controller.RequestsFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>requestFilter</filter-name>
<servlet-name>index</servlet-name>
</filter-mapping>
<servlet>
<servlet-name>index</servlet-name>
<jsp-file>/index.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>index</servlet-name>
<url-pattern>/index</url-pattern>
</servlet-mapping>
</web-app>
and here is the filter:
#WebFilter
public class RequestsFilter extends HttpServlet implements Filter {
static Logger log = Logger.getLogger("RequestFilter");
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
HttpServletResponse resp = (HttpServletResponse) servletResponse;
req.setAttribute("key", "some random string");
log.warning("**RequestFilter**");
filterChain.doFilter(req, resp);
}
}
Would appreciate any help, and thanks.

This is NOT a filter.
You are mixing up servlet and filters. Filter and Servlet are completely two different things.
public class RequestsFilter extends HttpServlet implements Filter {
I can see some issues in your web.xml as well. <servlet-name> should not be there in <filter-mapping>
<servlet-name>index</servlet-name>
You can find a simple yet clean example here.

Related

How to encrypt/decrypt data with filter in springMVC Web Project?

My project is some java web projects which using Spring+SpringMVC+Mybaits framework.Here is a requirement that encrypt some data like user's name,mobile,identify_number in database and post requirement.I have encrypt these colums in database.I add two filter in a project named mobile-project,which provide post service to other people.In the doFilter() method of filter,I replace the servletRequest with my encryptRequestWrapper,which extends HttpServletRequestWrapper.I Override its getParameter() method and encrypt some data in this method.It work well,data has been encrypted/decrypted well.
Now I copy this to other project,It did not work.Here is my filter code:
package com.xinrong.web.admin.security;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
public class RequestEncryptFilter implements Filter {
private Set<String> prefixUrls = new HashSet<String>();
#Override
public void init(FilterConfig filterConfig) throws ServletException {
String contextPath = filterConfig.getServletContext().getContextPath();
String ignoreStr = filterConfig.getInitParameter("ignoreReqPrefix");
String[] ignorePatterns = ignoreStr.split(",");
for (String prefix : ignorePatterns) {
prefixUrls.add(contextPath + prefix);
}
}
#Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
if (!isIgnoreUrl(req)) {
String requestType = (String) req.getHeader("X-Requested-With");
if (requestType != null && requestType.equals("XMLHttpRequest")) {
chain.doFilter(new RequestBodyEncryptWrapper(req), response);
} else {
chain.doFilter(new RequestEncryptWapper(req), response);
}
chain.doFilter(new RequestEncryptWapper(req), response);
} else {
chain.doFilter(request, response);
}
}
#Override
public void destroy() {
prefixUrls = null;
}
private boolean isIgnoreUrl(HttpServletRequest request) {
String url = request.getRequestURI();
for (String prefix : prefixUrls) {
if (url.startsWith(prefix)) {
return true;
}
}
return false;
}
}
package com.xinrong.web.admin.security;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import org.apache.commons.lang3.ArrayUtils;
import com.xinrong.service.bank.rongbao.pay.AES;
import com.xinrong.utils.UrlUtil;
public class RequestBodyEncryptWrapper extends HttpServletRequestWrapper {
private final byte[] body;
public RequestBodyEncryptWrapper(HttpServletRequest request)
throws IOException {
super(request);
ServletInputStream stream = request.getInputStream();
ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
byte[] buff = new byte[100];
int rc = 0;
while ((rc = stream.read(buff, 0, 100)) > 0) {
swapStream.write(buff, 0, rc);
}
this.body = swapStream.toByteArray();
String tmpStr=new String(body,"UTF-8");
System.out.println("request tmp str:"+tmpStr);
}
#Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
#Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream bais = new ByteArrayInputStream(body);
return new ServletInputStream() {
#Override
public int read() throws IOException {
return bais.read();
}
};
}
#Override
public String getParameter(String name) {
String queryUrl = getRequestPayload();
return UrlUtil.getEncryptPara(queryUrl, name);
}
#Override
public String[] getParameterValues(String name) {
String[] vals=super.getParameterValues(name);
if(ArrayUtils.contains(UrlUtil.encryptKeyArr, name)){
vals[0]=AES.encryptToBase64(vals[0]);
}
return vals;
}
private String getRequestPayload() {
StringBuilder sb = new StringBuilder();
try {
BufferedReader reader = getReader();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
return sb.toString();
}
}
package com.xinrong.web.admin.security;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.log4j.Logger;
import com.xinrong.service.bank.rongbao.pay.AES;
import com.xinrong.utils.UrlUtil;
public class RequestEncryptWapper extends HttpServletRequestWrapper {
public RequestEncryptWapper(HttpServletRequest request) {
super(request);
}
private Logger logger = Logger.getLogger(RequestEncryptWapper.class);
#Override
public String[] getParameterValues(String name) {
String[] strs = super.getParameterValues(name);
if (strs == null || strs.length == 0) {
return strs;
}
if (ArrayUtils.contains(UrlUtil.encryptKeyArr, name)) {
logger.info("before encrypt:" + strs[0]);
strs[0] = AES.encryptToBase64(strs[0]);
logger.info("after encrypt:stri is:" + strs[0]);
}
return strs;
}
}
Here is web.xml configuration.
<filter>
<filter-name>encryptRequestFilter</filter-name>
<filter-class>com.xinrong.web.admin.security.RequestEncryptFilter</filter-class>
<init-param>
<param-name>ignoreReqPrefix</param-name>
<param-value>/statics,/main,/login,/investor/getUnAuthStatusPage</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encryptRequestFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
The problem is that when I type "12345678912" as mobile value condition in this page,value of investorVO's mobile attribute is null,
queryPage
code in controller method:
* #param
* #param
* #param session
* #return
* #throws
*/
#RequestMapping(value = "dataGrid")
#ResponseBody
public EasyuiDataGrid dataGrid(InvestorVO investorVO, HttpSession session) {
return investorService.query(investorVO);
}
But if I invalid the filter,value of investorVO's mobile attribute get "12345678912".I guess something in SpringMVC cause this,but I don't know the exact reason.
-- EDIT
Version of SpringMVC is 3.2.8,it not support #requestBodyAdvice #responseBodyAdvice.
Here is web.xml configuration:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>backend</display-name>
<!-- 设置Spring容器加载配置文件路径 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/spring.xml</param-value>
</context-param>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:/log4j.properties</param-value>
</context-param>
<!-- 解决工程编码过滤器 -->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<!-- added LiYongjie encrypt -->
<filter>
<filter-name>encryptRequestFilter</filter-name>
<filter-class>com.xinrong.web.admin.security.RequestEncryptFilter</filter-class>
<init-param>
<param-name>ignoreReqPrefix</param-name>
<param-value>/statics,/main,/login,/investor/getUnAuthStatusPage</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encryptRequestFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<!-- Spring Security配置 -->
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
<!-- SpringSecurity 核心过滤器配置 -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- <filter> <filter-name>decryptResponseFilter</filter-name> <filter-class>com.xinrong.web.admin.security.ResponseDecryptFilter</filter-class>
<init-param> <param-name>ignoreResPrefix</param-name> <param-value>/statics,/main,/login,/investor/getUnAuthStatusPage</param-value>
</init-param> </filter> <filter-mapping> <filter-name>decryptResponseFilter</filter-name>
<url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher>
</filter-mapping> -->
<!-- 加载Spring容器配置 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 加载Log4j配置 -->
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<!-- 加载防止内存溢出监听器 -->
<listener>
<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>
<!-- 扩展Request作用域 scope="request" 分别是 singleton、prototype、request、session、global
session -->
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<!-- Spring MVC Servlet -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/config/spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--超时 -->
<session-config>
<session-timeout>600</session-timeout>
</session-config>
</web-app>
Perhaps I know the reason now.SpringMVC wrapper params from request to pojo Objects.Methods getInputStream(),getReader(),getParameter() from request can be invoked only once.I invoke getInputStream() in my RequestBodyEncryptWrapper Class,so when SpringMVC try to getParameter from request,it get null. But I still don't know how to do it.

Spring Security Configuration for POST request

I have configured spring security in my Rest API.I have three controller methods. One uses GET and other two use POST.
Now, I have used basic authentication.
The problem is that the security is working fine for GET request but not for the POST requests.
I am always getting 403 Forbidden response for the requests when POST method is used.
Controller class:
package com.base.controller;
import java.util.List;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.annotation.Secured;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import com.base.model.User;
import com.base.service.UserService;
#RestController
public class CountryController {
#Autowired
UserService userService; //Service which will do all data retrieval/manipulation work
//-------------------Retrieve All Users--------------------------------------------------------
#RequestMapping(value = "/user/", method = RequestMethod.POST)
public ResponseEntity<List<User>> listAllUsers() {
List<User> users = userService.findAllUsers();
if(users.isEmpty()){
return new ResponseEntity<List<User>>(HttpStatus.NO_CONTENT);//You many decide to return HttpStatus.NOT_FOUND
}
return new ResponseEntity<List<User>>(users, HttpStatus.OK);
}
//-------------------Retrieve Single User--------------------------------------------------------
#RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
public ResponseEntity<User> getUser(#PathVariable("id") long id) {
System.out.println("Fetching User with id " + id);
User user = userService.findById(id);
if (user == null) {
System.out.println("User with id " + id + " not found");
return new ResponseEntity<User>(HttpStatus.NOT_FOUND);
}
return new ResponseEntity<User>(user, HttpStatus.OK);
}
#RequestMapping(value = "/user123", method = RequestMethod.POST)
#ResponseStatus(HttpStatus.ALREADY_REPORTED)
public User postUser(#RequestBody #Valid User user) {
System.out.println("Fetching User with id " + user.getId());
user.setName("Tou added");
return user;
}
}
Security Config:
#Configuration
#EnableWebSecurity
#ComponentScan("com.base.security")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
MyUSerService userService;
#Autowired
public void configureGlobalAuth(final AuthenticationManagerBuilder auth)throws Exception{
auth.userDetailsService(userService);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
// TODO Auto-generated method stub
http.authorizeRequests().anyRequest().authenticated().and().httpBasic().and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
MyUserService (to provide the usename and password)
#Service
public class MyUSerService implements UserDetailsService{
#Override
public UserDetails loadUserByUsername(String arg0) throws UsernameNotFoundException {
// TODO Auto-generated method stub
List<SimpleGrantedAuthority> authoriities = new ArrayList<SimpleGrantedAuthority>();
authoriities.add(new SimpleGrantedAuthority("WRITE"));
return new User("ayush","ayush123",authoriities);
}
}
Web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<display-name>Archetype Created Web Application</display-name>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>springrest</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.base.config</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springrest</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
I am using 'Google Advanced Rest Client'.
You need to disable CRSF. CRSF is enabled by default in spring security 4.
http.csrf().disable()
or send the request with CRSF token.
In Spring Security 4.0, CSRF protection is enabled by default with XML configuration. You have to disable CSRF protection, the corresponding XML.
<http>
<!-- ... -->
<csrf disabled="true"/>
</http>
Or you to disable in Java configration file in code base by following
http.csrf().disable();

Only allow localhost with own filter, not with catalina

I'm making a Java webapplication. This webapplication is embedded in another application, and should only accept request from the localhost.
I saw different solutions which use the org.apache.catalina.valves.RemoteAddrValve dependency in their solutions, this is not applicable in my solution.
I'm trying to make my own Filter to do this, I get following configuration in my web.xml
<filter>
<filter-name>AccessFilter</filter-name>
<filter-class>com.search.watson.AccessFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AccessFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
I use following implementation:
public class AccessFilter implements Filter {
private PropertiesHelper propertiesHelper = new PropertiesHelper();
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
if (servletRequest.getRemoteHost().equals(propertiesHelper.getProperty("searchAllowedIP", "127.0.0.1"))) {
filterChain.doFilter(servletRequest, servletResponse);
} else {
System.out.println("Nothing happened");
}
}
#Override
public void destroy() {
}
}
My IP address of my server is 10.254.201.53, when I navigate to 10.254.201.53:8080/watson, this needs to block, when I access the search engine inside the application (10.254.201.53:8080/search), this needs to work.
But this doesn't seem to work, what can I do to make this work?

Servlet not working on WebSphere 8.x

I have the following class...
package org.me.test
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
#WebServlet("/servlet")
public class TestServlet extends HttpServlet {
/**
*
*/
private static final long serialVersionUID = 1L;
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// TODO Auto-generated method stub
resp.setContentType("text/plain");
resp.getWriter().write("Test Servlet");
super.doGet(req, resp);
}
}
and the following Web.xml...
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<servlet>
<display-name>srv</display-name>
<servlet-name>srv</servlet-name>
<servlet-class>
org.me.test.TestServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>srv</servlet-name>
<url-pattern>/srv/*</url-pattern>
</servlet-mapping>
</web-app>
but I get...
Error 405: HTTP method GET is not supported by this URL
You are getting the 405 error because you are calling super.doGet() at the end of your doGet(). Try removing that line.
The default implementation of doGet() in the base class HttpServlet returns that 405 error. To support the GET operation, you must override doGet() without calling the parent implementation, otherwise it returns the same error intended to be displayed when there is no override.

Problem in Context Listener

I was trying to run a servlet using ServletContextListener ,I've put the codes from the book
"Head-First" writter "Kathy sierra", but this is not working.Its shows 404 error.I have put the class files in the directory C:\Tomcat 5.5\webapps\Listener_exe\web-inf\classes\com\example. and web.xml file in web-inf directory. So please show where I have
done wrong. Here are the servlet, java files, and xml file.`
package com.example;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public class ListenerTester extends HttpServlet
{
public void doGet(HttpServletRequest request,HttpServletResponse response) throws IOException,ServletException
{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html><body>test context attributes set by listener<br>");
Dog dog = (Dog) getServletContext().getAttribute("dog");
out.println("Dog's breed is: "+dog.getBreed()+</body></html>);
}
}
package com.example;
public class Dog
{
private String breed;
public Dog(String breed)
{
this.breed=breed;
}
public String getBreed()
{
return breed;
}
}
package com.example;
import javax.servlet.*;
public class MyServletContextListener implements ServletContextListener
{
public void contextInitialized(ServletContextEvent event)
{
ServletContext sc = event.getServletContext();
String dogBreed = sc.getInitParameter("breed");
Dog d = new Dog(dogBreed);
sc.setAttribute("dog",d);
}
public void contextDestroyed(ServletContextEvent event)
{}
}
<web-app>
<servlet>
<servlet-name>ListenerTester</servlet-name>
<servlet-class>com.example.ListenerTester</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ListenerTester</servlet-name>
<url-pattern>/ListenerTester</url-pattern>
</servlet-mapping>
<Context-param>
<param-name>breed</param-name>
<param-value>Great Dane</param-value>
</Context-param>
<listener>
<listener-class>
com.example.MyServletContextListener
</listener-class>
</listener>
</web-app>
Did you use the correct URL to reach the page? Your URL should be something like,
http://localhost:8080/Listener_exe/ListenerTester
Use whatever hostname or port number you set for your connector.

Resources