CQ5: 403 Forbidden occurs when call a Post servlet
Asked Answered
P

4

7

Hi I'm using this code to create a Post method for my CQ5 example application.

package com.adobe.cq.sling;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.rmi.ServerException;
import java.util.Dictionary;

import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.sling.SlingServlet;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.apache.sling.commons.osgi.OsgiUtil;
import org.apache.sling.jcr.api.SlingRepository;
import org.apache.felix.scr.annotations.Reference;
import org.osgi.service.component.ComponentContext;
import javax.jcr.Session;
import javax.jcr.Node; 
import org.json.simple.JSONObject;
import java.util.UUID;

@SlingServlet(paths="/bin/mySearchServlet", methods = "POST", metatype=true)
public class HandleClaim extends org.apache.sling.api.servlets.SlingAllMethodsServlet {
     private static final long serialVersionUID = 2598426539166789515L;


     @Override
     protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServerException, IOException {

      try
      {
         //Get the submitted form data that is sent from the
              //CQ web page  
          String id = UUID.randomUUID().toString();
          String firstName = request.getParameter("firstName");
          String lastName = request.getParameter("lastName");
          String address = request.getParameter("address");
          String cat = request.getParameter("cat");
          String state = request.getParameter("state");
          String details = request.getParameter("details");
          String date = request.getParameter("date"); 
          String city = request.getParameter("city"); 

          //Encode the submitted form data to JSON
          JSONObject obj=new JSONObject();
          obj.put("id",id);
          obj.put("firstname",firstName);
          obj.put("lastname",lastName);
          obj.put("address",address);
          obj.put("cat",cat);
          obj.put("state",state);
          obj.put("details",details);
          obj.put("date",date);
          obj.put("city",city);

             //Get the JSON formatted data    
          String jsonData = obj.toJSONString();

             //Return the JSON formatted data
         response.getWriter().write(jsonData);
      }
      catch(Exception e)
      {
          e.printStackTrace();
      }
    }
}

it work ok with a GET request. But for a POST(doPost) request i recevied a message: 403 Forbidden. What i should do to resolve this issue ?

Peggi answered 1/4, 2014 at 23:46 Comment(2)
This should work perfectly. And it should throw an 405 GET not supported error when using GET request, as you havent implemented it. And for the POST it should work. Are you accessing this via a webserver? Have you checked whether the path /bin is allowed access in case you are accessing through a webserver?Headphone
Did you ever manage to solve this? I've got the exact same issue and cannot seem to figure out what the issue isDefection
P
11

This issue will never happen If you call the method from internal client (for example: jsp file, ajax or Servlets that located in your application). However if you call it from external client (another website or REST client plugin...) CQ security filter will be triggered to prevent your action then return 403 error to remove this please follow these steps:

1/ http://localhost:4502/system/console/configMgr
2/ Search for 'Apache Sling Referrer Filter'
3/ Remove POST method from the filter. Then you can call your POST method anywhere.

Peggi answered 2/9, 2015 at 3:21 Comment(3)
I did that but somehow removing POST from referrer filters is not persisting. Every time i restart AEM, it resets and add POST in list. Any idea to fix it?Inbred
Got it, a silly miss. I checked in my config in code with POST method removed. It worked.Inbred
you just have to add <cq:includeClientLib categories="granite.csrf.standalone" /> between the html head tag. or use jquery from aemElector
P
7

As mentioned at http://sling.apache.org/documentation/the-sling-engine/servlets.html, a servlet using the sling.servlet.paths property might be ignored unless its path is included in the Execution Paths (servletresolver.paths) configuration setting of the SlingServletResolver service. You should find that configuration at /system/console/configMgr/org.apache.sling.servlets.resolver.SlingServletResolver .

In your case I suppose the /bin/mySearchServlet path is not included in that configuration parameter and causes CQ to return a 403 status. If that's right you can either add your path there (assuming you understand the security implications) or mount your servlets on one of the paths that's configured there.

Note that it's best to avoid mounting servlet on paths if possible, creating a resource at the desired path is preferred as mentioned on that documentation page.

Prosciutto answered 2/4, 2014 at 8:57 Comment(2)
/bin/ would be available in the resolver config by default isn't it? So, it should take care of this by default. Please correct me if i am wrong. And btw, i have checked this code on my instance and it is working fine without any additional configuration.Headphone
Tien Nguyen didn't indicate if the system has a default config, so it's worth checking that. But you're right that if /bin is included in the config that I mentioned the servlet should work for POST requests.Prosciutto
T
7

In addition to the other answers, If you are on AEM 6.1 this issue can also be caused by a CSRF Configuration as explained on this post.

Short answer, check that the POST method is NOT in the filter methods of the CSRF filter config

http://localhost:4502/system/console/configMgr/com.adobe.granite.csrf.impl.CSRFFilter

Turfy answered 23/5, 2016 at 23:56 Comment(0)
M
2

I am also using the same code for similar set of requirements and i was stuck on this error. I have solved it.

PFB the steps. Either of them/All might work for you as well.

  1. I have however used the annotations differently.

    @Component( immediate = true, metatype = true, label = "Engage Now Form", description = "Engage Now Form") @Service @Properties({ @Property(name = "sling.servlet.paths", value = {"/bin/myServlet"}), @Property(name = "sling.servlet.methods", value = {"POST"}) })

  2. I have given permission to my /bin/myServlet in the org.apache.sling.servlets.resolver.SlingServletResolver.

  3. Used the poster plugin - set the referer in the header to some html existing in your site heirarchy other wise it will give 403 forbidden error. Also mention the parameters to send and go to content to send and say body from parameters. The below text box shall be populated. Now try posting the data.

  4. For the CQ specific part :- i have implemented an AJAX based solution with forms where i send the POST call using AJAX on submit click. I also have a custom action in place with a forward.jsp containing the following code.

    final ValueMap properties = ResourceUtil.getValueMap(resource); String path = properties.get("customRedirectPath", ""); //path = /bin/myServlet FormsHelper.setForwardPath(slingRequest, path); FormsHelper.setRedirectToReferrer(request, true);

My AJAX call is :-

 argsObject = {
            oServiceUrl: "/bin/myServlet",
            oAjaxFormat: "html",
            oDataForAjax: $thisForm.serialize(),
            oAjaxCommMethod: "POST",
            oSuccessCallback: onSubmitSuccessCallback,
            oErrorCallback: onSubmitErrorCallback
            }

I am able to execute my servlet once this POST call is executed and i recieve a valid response as desired.

Let me know if these steps help.

Meltwater answered 9/4, 2014 at 6:44 Comment(2)
I dont think POSTER plugin uses the browser cookies. This might be causing the forbidden error. Try postman - REST client for Chrome.Headphone
@Headphone :- It does use the browser cookies. The problem was that i was not mentioning the referer in the header which was causing this issue. It has now been resolved. Thanks :)Meltwater

© 2022 - 2024 — McMap. All rights reserved.