10
Drupal Sins How I learned to stop thinking and love sites that bomb. By: Aaron Crosman

Sins Against Drupal 2

Embed Size (px)

Citation preview

Page 1: Sins Against Drupal 2

Drupal Sins

How I learned to stop thinking and love sites

that bomb.

By: Aaron Crosman

Page 2: Sins Against Drupal 2

The Goal

Allow a blackbox third-party application

authenticate against Drupal and save/retrieve

data using custom REST-inspired interface.

Page 3: Sins Against Drupal 2

The sinful solution

Create a series of bootstrap scripts to handle

all the interactions, turning Drupal into a

glorified database layer (also while you’re at it,

bypass all SQL injection attack protections to

make sure Drupal provides as little value as

possible).

Page 4: Sins Against Drupal 2

Boot Drupal!

If you don’t give me what I want, I’ll pretend I’m not here...

No problem with that...nope

Page 5: Sins Against Drupal 2

If I don’t rename the variables how will I know what they are called.

I better pass my own hash of the authentication around that’s much

more secure than anything someone else might provide...

Yeah, nothing to see here. No problem with just dumping a variable

into SQL...nope. And why would I want to use $obj->uid when I can

save a character and use a variable.

If you can’t login, I’ll just pretend I’m not here, and use my own

magic status code...

Page 6: Sins Against Drupal 2

Again, nothing wrong with a variable or two in the SQL...

I loaded an object, now I’ll just put those into some variables, these

objects are awfully hard to work with...

Here’s a web page with a new query string in it. I hope that’s what you wanted. Too

bad there aren’t better formats for this...

Page 7: Sins Against Drupal 2

Better Solutions:

Use a custom menu to define paths, and have

the application just go there instead.

Use Services module:

https://www.drupal.org/project/services

Hire a call center to ask all your users for their

data.(dear God just don’t do what was done above.)

Page 8: Sins Against Drupal 2

function hook_menu() {

$items['games/auth'] = array(

'title' => 'Games Authorization',

'page callback' => 'game_module_auth_user',

'access arguments' => array('access content'),

'type' => MENU_CALLBACK,

);

$items['games/game_name/data'] = array( // yes, you could make that a variable instead of hard code

'title' => 'Game Data',

'page callback' => 'game_module_game_name_capture_data', // and if you did you could use one function and pass that variable

'access arguments' => array('player'),

'type' => MENU_CALLBACK,

);

return $items;

}

Page 9: Sins Against Drupal 2

Schema: If I need someplace for my data'fields' => array(

'recordID' => array(

'description' => 'The primary identifier for a record.',

'type' => 'serial',

...

'uid' => array(

'description' => 'The user ID.',

'type' => 'int',

...

'game' => array(

'description' => 'The game name',

'type' => 'text',

...

'data' => array(

'description' => 'Serialized data from Game application',

'type' => 'blob',

Page 10: Sins Against Drupal 2

function game_module_auth_user($user_name = '', $pass = '') { // Here I am using GET, but I don’t have to

global $user;

if($user->uid != 0) { // They are logged in already, so reject them

drupal_access_denied();

}

$account = user_authenticate($user_name, $pass);

//Generate a response based on result....

}

function game_module_[game_name]_capture_data() {

global $user;

if($user->uid == 0) { // They aren’t logged in, so they can’t save data

drupal_access_denied();

}

$record = drupal_get_query_parameters($query = $_POST); // ← we can work with POST just as well as GET if we ask Drupal

to look in the right place.

db_insert('game_data')

->fields(array(

'uid' => $user->uid, 'game' => '[game_name]', 'data' => serialize($record), ))

->execute();

// Provide useful response.

}