- 1. Как это сделать удобнее
2. Как это сделать безопаснее
- 1. На сервере 3 скрипта. (config.php, vkapi.class.php, core.php)
2. Взаимодействовать надо только со скриптом core.php
3. Надо чтобы были минимальные сложности в использовании
[Шаг 1: создаём среду для работы скрипта core.php]
Файл config.php :
Код: Выделить всё
<?php/*@Author : Alexandr Leutin {AlexProger, Xikke}*/define("DB_USER","..."); //Имя пользователя БДdefine("DB_PASS","..."); //Пароль БДdefine("DB_NAME","..."); //Имя БДdefine("DB_HOST","localhost"); define("API_ID","..."); //ID прилы в вкdefine("API_SECRET","........."); //Секретный ключ прилы function Connect(){ mysql_connect(DB_HOST, DB_USER, DB_PASS) or die (mysql_error()); mysql_select_db(DB_NAME) or die (mysql_error()); mysql_query("SET NAMES 'utf8'"); }?>
Файл vkapi.class.php :
Код: Выделить всё
<?php /** * VKAPI class for vk.com social network * * @package server API methods * @link http://vk.com/developers.php * @autor Oleg Illarionov * @version 1.0 */ class vkapi { var $api_secret; var $app_id; var $api_url; function vkapi($app_id, $api_secret, $api_url = 'api.vk.com/api.php') { $this->app_id = $app_id; $this->api_secret = $api_secret; if (!strstr($api_url, 'http://')) $api_url = 'http://'.$api_url; $this->api_url = $api_url; } function api($method,$params=false) { if (!$params) $params = array(); $params['api_id'] = $this->app_id; $params['v'] = '3.0'; $params['method'] = $method; $params['timestamp'] = time(); $params['format'] = 'json'; $params['random'] = rand(0,10000); ksort($params); $sig = ''; foreach($params as $k=>$v) { $sig .= $k.'='.$v; } $sig .= $this->api_secret; $params['sig'] = md5($sig); $query = $this->api_url.'?'.$this->params($params); $res = file_get_contents($query); return json_decode($res, true); } function params($params) { $pice = array(); foreach($params as $k=>$v) { $pice[] = $k.'='.urlencode($v); } return implode('&',$pice); }}?>
Для начала определим задачи и список функций выполняемых скриптом.
- 1. Авторизация пользователя
2. Получение его данных из БД
3. Запись данных в БД
Код: Выделить всё
CREATE TABLE IF NOT EXISTS `users` ( `id` int(9) auto_increment, `uid` int(9), `money` int(6) default '100', `rait` int(8) default '0', `last_enter` int(15), PRIMARY KEY (`id`), UNIQUE KEY `uid` (`uid`)) ENGINE=MyISAM DEFAULT CHARSET=utf8;
- id - номер в базе
uid - ID пользователя в вк
money - кол-во денег в приле
rait - рейтинг в приле
last_enter - UNIX время последнего захода (защитимся от захода в прилу через каждые 5 секунд)
Естественно передавая переменную act вот варианты её значения :
- AUTH_USR - пользователь хочет авторизироваться
GET_USER_INFO - получаем данные о юзере
UPDATE_USER_INFO - обновляем данные о юзере
Итак часть 1 : подключаем ранее написанные файлы :
Код: Выделить всё
include 'config.php';require 'vkapi.class.php';
Теперь получим обязательные данные которые нужны скрипту :
Код: Выделить всё
$uid = $_POST['viewer_id'];$auth = $_POST['auth_key'];$act = $_POST['act'];$key = $_POST['key'];
- $uid - ID пользователя в вк
$auth - auth_key пользователя
$act - наша переменная обозначающая что мы хотим делать
$key - ключ защиты переменной act
$key - это хэш защищающий от подмены не только $act, но и $uid и $auth.
Вот формула (защита идёт через MD5, хотя мы спокойно могли бы использовать и SHA1 и другие алгоритмы защиты данных, но такой задачи нам не ставилось и мы не ищем лёгких путей )
Нам пора использовать полученные данные, я решил не расписывать каждый шаг и представил каркас ниже :
Код: Выделить всё
<?phpinclude 'config.php';require 'vkapi.class.php';Connect();/* @desc: Загрузка переменных*/$uid = $_POST['uid'];$auth = $_POST['auth'];$act = $_POST['act'];$key = $_POST['key'];/* @desc: Обработка данных*/if ($auth == md5(API_ID.'_'.$uid.'_'.API_SECRET)){ if (md5(md5($act).md5($auth).md5($uid)) == $key){ switch($act) { case "AUTH_USR": //Авторизация break; case "GET_USER_INFO": //Получение данных break; case "UPDATE_USER_INFO": //Обновление данных break; default: //Неизвестный акт break; } }else{ //Ошибка в key (скорее всего подмена данных }}else{//Ошибка в auth_key }?>
Итак продолжим реализацию :
Теперь нам надо записать пользователя в БД, код представлен ниже :
Код: Выделить всё
$result = mysql_query('INSERT INTO `users` (`uid`, `last_enter`) VALUES ("'.$uid.'","'.time().'") ON DUPLICATE KEY UPDATE `last_enter` = "'.time().'";');if (!$result){//Ошибка mysql запроса выводим её в ответ :exit('{"error":"1","desc":"mysql error '.mysql_error().'}');}else{//Выводим что всё хорошоexit('{"error":"0","auth":"1","hash":"'.md5(md5('1_auth_1')).'"}');}
Я делаю запрос на занесение пользователя в базу и в случае ошибки выдаю пользователю в виде JSON ответа.
Думаю ничего сложного в этом нет поэтому приступим к рассмотрению второго вида акта : GET_USER_INFO
Я не буду разъяснять что мы делаем в этом акте т.к. это за меня сделал Александр (Тыц чтобы посмотреть урок) поэтому вот код :
Код: Выделить всё
$result = mysql_query('SELECT * FROM `users` WHERE `uid`='.$uid.';');if (!$result){//Ошибка mysql запроса выводим её в ответ :exit('{"error":"1","desc":"mysql error '.mysql_error().'}');}else{$data = mysql_fetch_assoc($result); //mysql_fetch_assoc потому что нам надо обращаться к переменныем таким способом : $data['money'];//Создаём переменные которые надо вывести : $money = $data['money'];$rait = $data['rait'];$hash = md5(md5($money).md5($rait));//Выводим результатexit('{"error":"0","money":"'.$money.'","rait":"'.$rait.'","hash":"'.$hash.'"}');}
Сейчас я немного отойду от темы и мы поговорим о безопасности этого акта.
Данный акт требует дополнительные данные (кол-во добавляемых едениц) и нам надо защитить эти данные. Поэтому мы будем принимать к этому методу не 2 параметра, а 3.
Параметры :
- 1. money - это сколько надо добавить денег
2. rait - это сколько надо добавить рейтинга
3. checker - это хэш данных (защищает только money и rait и привязан к auth_key)
md5(money + auth + rait);
Вот код третьего акта :
Код: Выделить всё
$money = $_POST['m_add']; //Внимание : я использовал именование m_add, r_add вместо money и rait$rait = $_POST['r_add']; //$hash = $_POST['c_add']; //c_add это checkerif (md5($money.$auth.$rait) == $hash){ $result = mysql_query('UPDATE `users` SET `money` = `money` + "'.$money.'", `rait` = `rait` + "'.$rait.'" WHERE `uid`='.$uid.';'); if (!$result) { exit('{"error":"1","desc":"mysql error '.mysql_error().'}'); }else{ //Обновляем данные и выводим их $result_2 = mysql_query('SELECT * FROM `users` WHERE `uid`='.$uid.';'); if (!$result_2){ exit('{"error":"1","desc":"mysql error '.mysql_error().'}'); }else{ //Выводим обновлённые данные [код из акта 2] $data = mysql_fetch_assoc($result); //mysql_fetch_assoc потому что нам надо обращаться к переменныем таким способом : $data['money']; //Создаём переменные которые надо вывести : $money = $data['money']; $rait = $data['rait']; $hash = md5(md5($money).md5($rait)); //Выводим результат exit('{"error":"0","money":"'.$money.'","rait":"'.$rait.'","hash":"'.$hash.'"}'); } }}else{//Попытка обманаexit('{"error":"1","desc":"invalid hash"}');}
Код: Выделить всё
<?phpinclude 'config.php';require 'vkapi.class.php';Connect();/* @desc: Загрузка переменных*/$uid = $_POST['uid'];$auth = $_POST['auth'];$act = $_POST['act'];$key = $_POST['key'];/* @desc: Обработка данных*/if ($auth == md5(API_ID.'_'.$uid.'_'.API_SECRET)){ if (md5(md5($act).md5($auth).md5($uid)) == $key){ switch($act) { case "AUTH_USR": //Авторизация $result = mysql_query('INSERT INTO `users` (`uid`, `last_enter`) VALUES ("'.$uid.'","'.time().'") ON DUPLICATE KEY UPDATE `last_enter` = "'.time().'";'); if (!$result){ //Ошибка mysql запроса выводим её в ответ : exit('{"error":"1","desc":"mysql error '.mysql_error().'}'); }else{ //Выводим что всё хорошо exit('{"error":"0","auth":"1","hash":"'.md5(md5('1_auth_1')).'"}'); } break; case "GET_USER_INFO": //Получение данных $result = mysql_query('SELECT * FROM `users` WHERE `uid`='.$uid.';'); if (!$result){ //Ошибка mysql запроса выводим её в ответ : exit('{"error":"1","desc":"mysql error '.mysql_error().'}'); }else{ $data = mysql_fetch_assoc($result); //mysql_fetch_assoc потому что нам надо обращаться к переменныем таким способом : $data['money']; //Создаём переменные которые надо вывести : $money = $data['money']; $rait = $data['rait']; $hash = md5(md5($money).md5($rait)); //Выводим результат exit('{"error":"0","money":"'.$money.'","rait":"'.$rait.'","hash":"'.$hash.'"}'); } break; case "UPDATE_USER_INFO": //Обновление данных $money = $_POST['m_add']; //Внимание : я использовал именование m_add, r_add вместо money и rait $rait = $_POST['r_add']; // $hash = $_POST['c_add']; //c_add это checker if (md5($money.$auth.$rait) == $hash){ $result = mysql_query('UPDATE `users` SET `money` = `money` + "'.$money.'", `rait` = `rait` + "'.$rait.'" WHERE `uid`='.$uid.';'); if (!$result) { exit('{"error":"1","desc":"mysql error '.mysql_error().'}'); }else{ //Обновляем данные и выводим их $result_2 = mysql_query('SELECT * FROM `users` WHERE `uid`='.$uid.';'); if (!$result_2){ exit('{"error":"1","desc":"mysql error '.mysql_error().'}'); }else{ //Выводим обновлённые данные [код из акта 2] $data = mysql_fetch_assoc($result); //mysql_fetch_assoc потому что нам надо обращаться к переменныем таким способом : $data['money']; //Создаём переменные которые надо вывести : $money = $data['money']; $rait = $data['rait']; $hash = md5(md5($money).md5($rait)); //Выводим результат exit('{"error":"0","money":"'.$money.'","rait":"'.$rait.'","hash":"'.$hash.'"}'); } } }else{ //Попытка обмана exit('{"error":"1","desc":"invalid hash"}'); } break; default: //Неизвестный акт exit('{"error":"1","desc":"unknown act"}'); break; } }else{ //Ошибка в key (скорее всего подмена данных exit('{"error":"1","desc":"key invalid"}'); }}else{//Ошибка в auth_keyexit('{"error":"1","desc":"auth key invalid"}');}?>
[шаг 4: пишем клиент]
Я не буду описывать весь процесс создания приложения поэтому приведу ниже код и расскажу о некоторых особенностях.
Код: Выделить всё
Файл [b]ServerAPI.as[/b] :package { import flash.net.*; import flash.events.*; import vk.api.MD5; import vk.api.serialization.json.JSON; public class ServerAPI { private var server:String = null; private var uid:String = null; private var auth:String = null; public function ServerAPI(parms:Object) { server = parms.url; uid = parms.uid; auth = parms.auth; } public function Executure(parms:Object){ /* Код представленный ниже взят из основы написанной в данной теме : http://flapps.ru/forum/topic165.html */ var core_loader:URLLoader = new URLLoader(); var core_request:URLRequest=new URLRequest(server + "core.php"); core_request.method=URLRequestMethod.POST; switch (parms.act) { case "AUTH_USR": core_vars['viewer_id'] = uid; core_vars['auth_key'] = auth; core_vars['act'] = parms.act; core_vars['key'] = MD5.encrypt(MD5.encrypt(parms.act) + MD5.encrypt(auth) + MD5.encrypt(uid)); //Больше параметров нет break; case "GET_USER_INFO": core_vars['viewer_id'] = uid; core_vars['auth_key'] = auth; core_vars['act'] = parms.act; core_vars['key'] = MD5.encrypt(MD5.encrypt(parms.act) + MD5.encrypt(auth) + MD5.encrypt(uid)); //Больше параметров нет break; case "UPDATE_USER_INFO": core_vars['viewer_id'] = uid; core_vars['auth_key'] = auth; core_vars['act'] = parms.act; core_vars['key'] = MD5.encrypt(MD5.encrypt(parms.act) + MD5.encrypt(auth) + MD5.encrypt(uid)); //Прочие параметры core_vars['m_add'] = parms.money; core_vars['r_add'] = parms.rait; core_vars['c_add'] = MD5.encrypt(parms.money + auth + parms.rait); break; default: throw new Error("Act is not valid"); break; } var core_vars:URLVariables = new URLVariables(); core_request.data=core_vars; core_loader.addEventListener(Event.COMPLETE, function(e:Event){ trace(e.target.data); //Для отладки var data:Object = JSON.decode(e.target.data); if (data['error'] == '0'){ //Ошибок нет parms.onComplete(data); }else{ parms.onError(data); } }); core_loader.addEventListener(IOErrorEvent.IO_ERROR, function(e:Event){ //Если ошибка из - за отсуствия доступа к скрипту parms.onError({error:1,desc:"IO_SCRIPT_ERROR"}); //Даём понять что ошибка не в скрипте }); core_loader.load(core_request); } }}
- 1. Только 1 аргумент во всех функциях (включая конструктор)
2. Обработка всех основных событий
3. Дополняемость класса (вы можете дописать класс или переделать его)
Код: Выделить всё
var net:ServerAPI = new ServerAPI({url:"http://myserver.ru/",uid:"ваш ID",auth:"ваш auth key"}); net.Executure({onComplete: function(data:Object){ //Успешный запрос }, onError: function(data:Object){ //Ошибка } });
От себя : Поздравляю всех с днём знаний
P.S. В данном уроке я не рассмотрел проверку времени последнего захода (защита от частых заходов). Это будет ваша домашняя работа