I'm writing a small servlet to prevent spam requests from an J2ME app. But, i don't know how to do this.
Could you help me or suggest to me some links/posts about this?
I assume you have another Servlet that handles 'valid' requests and you want spam requests to be filtered out?
If that is so, then you need a Filter.
You would configure it in your web.xml (or by annotation) to be applied to all requests going to your actual Servlet and implement it like that:
public class SpamFilter implements Filter {
#Override
public void init(FilterConfig config) throws ServletException {
// maybe read some configuration, e.g. rules that say what is spam and what is not
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if (isValidRequest(request)) {
chain.doFilter(request, response);
} else {
// request is spam, prevent further processing (so, do nothing)
}
}
#Override
public void destroy() {}
}
Related
I need to create a gated content setup in aem. So basically, the page ( which contains some assets) should only be reachable after the user has submitted a form. And the assets should also be not accessible directly without submitting the form. So I have created a servlet filter to achieve this, the page logic works fine but when I access assets directly the request is not reaching the servlet filters. The below is my code please let me know if there is some mistake or there is any other preferred method, I have also tried setting this ServiceRanking(1)
#Component(service = Filter.class,
property = {
EngineConstants.SLING_FILTER_SCOPE + "=" + EngineConstants.FILTER_SCOPE_REQUEST,
})
#ServiceRankin(-700)
public class GatedContentFilter implements Filter {
#Override
public void doFilter(final ServletRequest request, final ServletResponse response,
final FilterChain filterChain) throws IOException, ServletException {
final SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) request;
final SlingHttpServletResponse slingResponse = (SlingHttpServletResponse) response;
final Resource resource = slingRequest.getResource();
if(resource.getPath().startsWith("/content/abc")) {
//page logic
}
else if (resource.getPath().startsWith("/content/dam/abc/gated-assets")) {
//assets logic
}
filterChain.doFilter(request, response);
}
#Override
public void init(FilterConfig filterConfig) {
}
#Override
public void destroy() {
}
}
My configuration of Spring Security is
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/resources/**"); // #3
}
Taken from here.
The documentation for ignorig says
Allows adding RequestMatcher instances that should that Spring Security should ignore. ... Typically the requests that are registered should be that of only static resources.
I would like to add some headers to files served from resources.
E.g.: Strict-Transport-Security: max-age=31536000, X-Content-Type-Options: nosniff.
How I can do it?
One solution it to change it to
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/resources/**").permitAll()
.and()
.antMatcher("/resources/**").headers().cacheControl()
}
Example how to allow cache control headers PLUS ALL DEFAULT SPRING SECURITY HEADERS.
I have struggled with the same problem. When I ignore specific requests in WebSecurity, the headers were gone.
I fixed the missing headers, by applying a filter on each request that adds my headers.
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(securityHeaderFilter, BasicAuthenticationFilter.class)
...
}
The filter code looks like this. The important thing to note here, is that the Filter must be declared as a #Component. When you miss the #Component annotation, the filter will be ignored.
#Component
public class SecurityHeaderFilter implements Filter {
#Override
public void init(FilterConfig fc) throws ServletException {
// Do nothing
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
httpServletResponse.setHeader(
"custom-header1", "header-value1");
httpServletResponse.setHeader(
"custom-header2", "header-value2");
chain.doFilter(request, response);
}
#Override
public void destroy() {
// Do nothing
}
}
I have used the following solution:
#Bean
public FilterRegistrationBean setHeaders() {
HstsHeaderWriter hstsHeaderWriter = new HstsHeaderWriter(31536000, true);
XContentTypeOptionsHeaderWriter xContentTypeOptionsHeaderWriter = new XContentTypeOptionsHeaderWriter();
List<HeaderWriter> headerWriters = new ArrayList<>();
headerWriters.add(hstsHeaderWriter);
headerWriters.add(xContentTypeOptionsHeaderWriter);
HeaderWriterFilter headerWriterFilter = new HeaderWriterFilter(headerWriters);
FilterRegistrationBean bean = new FilterRegistrationBean(headerWriterFilter);
bean.setOrder(1);
return bean;
}
The above bean will add a filter globally on all the resources(even the ignoring ones). You can checkout the various implementations of org.springframework.security.web.header.HeaderWriter.java for the different kinds of security headers and add them all to HeaderWriterFilter.java.
Assume I have some servlets called /servlet1, /servlet2, etc in my code.
My goal is to serve two different applications with the same set of servlets:
/myapp1/servlet1 -> use /login with a parameter called myapp1
/myapp2/servlet2 -> use /login with a parameter called myapp2
I guess I have to use filter and filter mapping but I had no luck make it work so far.
here is an exemple of filter:
public class LoginFilter implements Filter {
public LoginFilter() {
// TODO Auto-generated constructor stub
}
public void destroy() {
// TODO Auto-generated method stub
}
public String clean(String s){
s=s.replaceAll("[^a-zA-Z0-9]", "");
s=s.trim();
return s;
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req=(HttpServletRequest) request;
HttpServletResponse resp=(HttpServletResponse) response;
String user=req.getParameter("username");
String pass=req.getParameter("password");
req.removeAttribute("username");
req.removeAttribute("password");
user=clean(user);
pass=clean(pass);
req.setAttribute("username", user);
req.setAttribute("password", pass);
chain.doFilter(req, response);
}
public void init(FilterConfig fConfig) throws ServletException {
}
}
and here is web.xml
<filter>
<filter-name>LoginFilter</filter-name>
<filter-class>pack.LoginFilter</filter-class> </filter>
<filter-mapping>
<filter-name>LoginFilter</filter-name>
<url-pattern>/some-url-patter</url-pattern> </filter-mapping>
you have to have the same url pattern as the servlets too add the filter. you can have any number of filters.
it works something like this : filter1->filter2->filter3->...->servlet
I'm using the servlet which redirects me with the help of
dispatcher.forward(request, response);
in the end. But after this I want to get the page(path) from which I was redirected to use it in next servlet command(to go to previous page). How could I get it?
Or previous URL is not contained in request parameters and I should add it myself?
Will be very grateful for your help.
String referer = request.getHeader("Referer");
response.sendRedirect(referer);
SEE:
Link to forum answer
Try using
request.getAttribute("javax.servlet.forward.request_uri")
See
https://tomcat.apache.org/tomcat-9.0-doc/servletapi/constant-values.html
and
How to get the url of the client
Any method will return source URL when you do forward(..) so my solution is to define a filter to store the requestURL() in a request attribute to check later. To do this in your web.xml write:
...
<filter>
<filter-name>MyFilter</filter-name>
<filter-class>my.package.CustomFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping>
...
Then in CustomFilter class:
public class CustomFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {}
#Override
public void destroy() {}
#Override
public void doFilter(ServletRequest req, ServletResponse rsp,
FilterChain chain) throws IOException, ServletException {
req.setAttribute("OriginURL", req.getRequestURL().toString());
chain.doFilter(req, rsp);
}
}
Then you can get it everywhere in your code with ServletRequest object with:
request.getAttribute("OriginURL").toString();
you can store that url in HttpSession and retrieve it in next servlet when you need.
I have the following servlet:
public class MyServlet extends HttpServlet {
private static final long serialVersionUID = 16252534;
private static int ping = 3000;
private Thread t;
private static boolean shouldStop = false;
#Override
public void init() throws ServletException {
super.init();
t = new Thread(new Runnable() {
#Override
public void run() {
while(!shouldStop) {
System.out.println("Now:" + System.currentTimeMillis());
try {
Thread.sleep(ping);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
t.start();
}
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
super.doGet(req, resp);
System.out.println("doGet");
PrintWriter out = resp.getWriter();
out.println("<html><h1>It works!!</h1></html>");
}
#Override
public void service(ServletRequest req, ServletResponse resp) throws ServletException, IOException {
super.service(req, resp);
System.out.println("service");
}
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
System.out.println("doPost");
}
#Override
public void destroy() {
super.destroy();
System.out.println("Destroy servlet");
shouldStop = true;
}
}
Which is mapped as follows in my web.xml:
<display-name>MyServer</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>com.myserver.MyServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/MyServlet</url-pattern>
</servlet-mapping>
When I open my browser (Chrome) on http://localhost:8080/MyServer/MyServlet, then I see "service" from doService() being logged on console and my thread works correctly, however I don't see "It Works" from doGet() being logged and I get the following error in the browser:
HTTP method GET is not supported by this URL
How is this caused and how can I solve it?
This is the default response of the default implementation of HttpServlet#doXxx() method (doGet(), doPost(), doHead(), doPut(), etc). This means that when the doXxx() method is not properly being #Overriden in your servlet class, or when it is explicitly being called via super, then you will face a HTTP 405 "Method not allowed" error.
So, you need to make sure that you have the doXxx() method properly declared conform the API, including the #Override annotation just to ensure that you didn't make any typos. E.g.
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// ...
}
And you also need to make sure that you don't ever call super.doXxx() in your servlet method:
super.doGet(request, response);
Your servlet has this. Just get rid of this line and your problem shall disappear.
The HttpServlet basically follows the template method pattern where all non-overridden HTTP methods returns this HTTP 405 error "Method not supported". When you override such a method, you should not call super method, because you would otherwise still get the HTTP 405 error. The same story goes on for your doPost() method.
This also applies on service() by the way, but that does technically not harm in this construct since you need it to let the default implementation execute the proper methods. Actually, the whole service() method is unnecessary for you, you can just remove the entire method from your servlet.
The super.init(); is also unnecessary. It's is only necessary when you override the init(ServletConfig), because otherwise the ServletConfig wouldn't be set. This is also explicitly mentioned in the javadoc. It's the only method which requires a super call.
Unrelated to the concrete problem, spawning a thread in a servlet like that is a bad idea. For the correct approach, head to How to run a background task in a servlet based web application?
you have overridden the service method which is responsible to delegate the call to doGet or doPost. see this for more details
Also get rid of super.doxxx(..) calls from each method.
Don't override the service method and you should see, "It Works" from doGet.