0

I am creating a PHP page that takes input via request parameters. My design currently routes all actions through one action.php which contains a function like this:

function get_param($name, $default_value=null) {
  $value = @$_GET[$name];
  if ($value == null) {
    $value = @$_POST[$name];
    if ($value == null) {
        $value = $default_value;
    }
  }
  return $value;
}

Then there is some other code that will look at the parameters on the request to tell what kind of action it is, each action can take other parameters. The action code would look something like this:

$action = get_param("action");
switch ($action) {
case "login":
  login(get_param("user_name"), get_param("password");
  break;
case "create_todo":
  create_todo(get_param("todo"));
  break;
case "get_todo":
  get_todo();
  break;
// Various other cases
}

Now let's assume that this PHP page is accessible through the internet as a general service for any website to use. As you can see, the actions contains things like login, and many other actions.

Also, let's assume that I properly validate each request (in terms of permissions as well as input length, etc).

Are there any risks in allowing the user the ability to choose if the request is a GET or a POST, and the action.php will work either way?

Should certain actions should be forced to POST (such as login, or create_todo) and others to GET (such as get_todo)?

codefactor
  • 1,616
  • 2
  • 18
  • 41
  • 1
    You should be specific, unless the variable is a router, e.g. GET[go] and POST[go] tell your code to include a particular file with required functions/class that would be used for both instances. Also it's better to use isset() than suppress errors. – Popnoodles Jan 06 '14 at 20:17
  • 2
    I'd definitely restrict any option that causes changes (e.g. a database delete, file removal, etc... **ANYTHING** that is non-idempotent) to POST only. Read [The Spider of Doom](http://thedailywtf.com/Articles/The_Spider_of_Doom.aspx) to find out why allowing arbitrary (dangerous) options via GET is a bad idea... – Marc B Jan 06 '14 at 20:18
  • 2
    If you're going to have wacky cascading sets anyway, why not use the superglobal [$_REQUEST](http://www.php.net/manual/en/reserved.variables.request.php)? – Digital Chris Jan 06 '14 at 20:20
  • There's nothing wacky about a function that checks if $_GET is set before getting it and also has the option to set a default. – Popnoodles Jan 06 '14 at 20:21
  • I agree with what you say here, @Popnoodles, however the error-supressing cascading code in the question could be defined as... a tad wacky? – Digital Chris Jan 06 '14 at 20:26
  • Oh that's what you mean, yes it should be using isset() not suppressing errors. – Popnoodles Jan 06 '14 at 20:27
  • @codefactor, I have a similar set of functions, `get()`, `post()`, `getPost()` (checks get first), `postGet()` (checks post first) and `which()` (takes any number of variables and returns the first truthy one, it is used by getPost and postGet). – Popnoodles Jan 06 '14 at 20:32
  • Thanks for the comments about the suppressing errors. I suppose I should be using `if (isset($_GET[$name]))` rather than suppress errors. – codefactor Jan 06 '14 at 21:30
  • @codefactor it would be just as easy to use a ternary expression: `$value = isset($_GET[$name]) ? $_GET[$name] : null;` – Jeff Lambert Jan 06 '14 at 21:33

2 Answers2

1

I would suggest not allowing the same functionality for different types of access. One reason is because if I do a GET request for /login, I should be shown the login form. If I POST to /login, the application should attempt to authenticate me, and then redirect to another location depending on the results (this basically is creating a semantic difference between the two). Remember the difference between the HTTP verbs: GET requests are meant for those that do not modify anything on the server, whereas POST requests can.

For further info, checkout the wikipedia entry on REST, and read also about RESTful controllers.

Community
  • 1
  • 1
Jeff Lambert
  • 24,395
  • 4
  • 69
  • 96
1

First, understand that GET and POST can be use together in a single request. Consider this html segment.

<form action="myscript.html?user_name=Bob" method='post'>
<input name='user_name'>
  :
</form>

In this case, both $_GET['user_name'] and $_POST['user_name'] will both have valid values for a form submission.

The risks are the same. but post allows you more control over submissions.

According to RFC2616. GET requests are 'safe' requests and should typically be used for requests that can be repeatable (for example the 'contact us' page).

POST requests are used for unsafe requests that should not be repeated, for example, ordering a book on an e-commerce site. (Ordering another book of the same title should be deemed a separate transaction). Browsers often help by not caching post requests, hence you often get a warning when repeating a post request by refreshing the browser window.

POST requests can send data that is not visible to the end user, whereas all data sent via a GET request can be seen in the URL.

As a general rule, send processing type data via GET (eg http://www.thesite.com/show_article?article_id=1), and user-type data by post (for example, login-data, product data).

Refer to my post on this difference : Parameters in POST url

Community
  • 1
  • 1
crafter
  • 6,246
  • 1
  • 34
  • 46