Viewed   76 times

When making an ajax call, when contentType is set to application/json instead of the default x-www-form-urlencoded, server side (in PHP) can't get the post parameters.
in the following working example, if I set the contentType to "application/json" in the ajax request, PHP $_POST would be empty. why does this happen? How can I handle a request where contentType is application/json properly in PHP?

$.ajax({
    cache: false,
    type: "POST",
    url: "xxx.php",
    //contentType: "application/json",
    processData: true,
    data: {my_params:123},
    success: function(res) {},
    complete: function(XMLHttpRequest, text_status) {}
});

 Answers

2
<?php
   var_dump(json_decode(file_get_contents('php://input')));
?>
Tuesday, November 1, 2022
3
<?php
$jsonurl = "http://api.wipmania.com/json";
$json = file_get_contents($jsonurl);
var_dump(json_decode($json));
?>

You just need json not jsonp.
You can also try using json_decode($json, true) if you want to return the array.

Tuesday, September 6, 2022
 
erik
 
4

My concern is that if someone steals this url ( https://example.com/retrieveData.php ), he can manually send fake post requests and can steal the returned user information?

You are right to be concerned. Anybody can send a message to that URL, and get the result unless you check some part of the request that authorizes the request.

For example, you could authenticate to check that the request comes from the user and then authorize the request based on the idea that the user should have access to that info.

Alternatively, you can authorize based on something that only a valid requestor would know via a shared secret and rely on the https part of that URL to prevent shared secrets from becoming public. You give out the secret to trusted partners, and when you generate a web form via PHP (also protected via HTTPS), you include a hidden input containing the shared secret. This is how XSRF protection typically works.

You should think about the following:

  1. Who should legitimately be able to reach this page? Logged-in users interacting via your phone app, partners who can protect a secret, web API users?
  2. What credentials do they have for using other parts of your server? Log-in cookies? XSRF tokens? Partner tokens?
  3. What parts of your app are sent only over secure channels like https?

If all of (1) is satisfied by some subset of credentials in (2) and those credentials are only ever sent over (3) then you just need to check (2) in your page. Otherwise, you need to rework your application architecture until that is true.

OWASP has a Guide to Authorization that might come in handy and they also have a number of pages on reviewing authorization code but most of the examples are not PHP specific.

Thursday, November 17, 2022
1

I figured it out!

if(empty($data['errors'])) {

    $data['success'] = true;

    $inputs = $_POST['inputs'];
    $email = $inputs[0]['value']; // I select the first element in my array, then I select its value
    $password = $inputs[1]['value']; // I select the second element in my array, then I select its value

    $query = "INSERT INTO users (email, password)

    VALUES

    ('{$email}', '{$password}')";

}
Monday, October 10, 2022
 
exts
 
3

WCF provides a lot of extensible points one of them is a feature called MessageInspector. You can create a custom message inspector to receive the request before it get de-serialized to C# object. And do what ever you can with Raw request data.

In order to implement it you would need to implement System.ServiceModel.Dispatcher.IDispatchMessageInspector interface like below:

public class IncomingMessageLogger : IDispatchMessageInspector
{
    const string MessageLogFolder = @"c:temp";
    static int messageLogFileIndex = 0;

    public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
    {
        string messageFileName = string.Format("{0}Log{1:000}_Incoming.txt", MessageLogFolder, Interlocked.Increment(ref messageLogFileIndex));
        Uri requestUri = request.Headers.To;

        HttpRequestMessageProperty httpReq = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name];

        // Decode the message from request and do whatever you want to do.
        string jsonMessage = this.MessageToString(ref request);

        return requestUri;
    }

    public void BeforeSendReply(ref Message reply, object correlationState)
    {
    }
}

Here's the complete code snippet gist. Actual source.

Now you need to add this Message inspector to end point behavior. To achieve that you would be implementing System.ServiceModel.Description.IEndpointBehavior interface like below:

public class InsepctMessageBehavior : IEndpointBehavior
{
    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
    }

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
    {
        endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new IncomingMessageLogger());
    }

    public void Validate(ServiceEndpoint endpoint)
    {
    }
}

Now if you are on selfhosting i.e. you are hosting your service programmatically you can directly attach this newly implemented behavior to your service end point. E.g.

endpoint.Behaviors.Add(new IncomingMessageLogger());

But If you have hosted the WCF Rest service in IIS then you would be injecting the new Behavior via configuration. In order to achieve that you have to create an additional class derived from BehaviorExtensionElement:

public class InspectMessageBehaviorExtension : BehaviorExtensionElement
{
    public override Type BehaviorType
    {
        get { return typeof(InsepctMessageBehavior); }
    }

    protected override object CreateBehavior()
    {
        return new InsepctMessageBehavior();
    }
}

Now in your configuration first register the behavior under system.servicemodel tag:

    <extensions>
      <behaviorExtensions>
        <add name="inspectMessageBehavior" 
type="WcfRestAuthentication.MessageInspector.InspectMessageBehaviorExtension, WcfRestAuthentication"/>
      </behaviorExtensions>
    </extensions>

Now add this behavior to the Endpoint behavior:

  <endpointBehaviors>
    <behavior name="defaultWebHttpBehavior">
      <inspectMessageBehavior/>
      <webHttp defaultOutgoingResponseFormat="Json"/>
    </behavior>
 </endpointBehaviors>

set the attribute behaviorConfiguration="defaultWebHttpBehavior" in your endpoint.

That's it your service will now capture all the messages before deserializing them.

Friday, October 28, 2022
 
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :