Вернуться   Дизайнерский форум » РАЗНОЕ » Кальянная

Опять про скретч-карты

Обсуждение темы Опять про скретч-карты в разделе Кальянная, часть категории РАЗНОЕ; Есть карты предоплаты (скретч-карты) с пин-кодом и номером карты. Пример: Номер: 225-657 Пин-код: 1598632747525514 Схема работы с картами такова: Пользователь выбирает в интернет-магазине ...


Закрытая тема
 
Опции темы
Старый 19.07.2007, 16:28   #1
Есть карты предоплаты (скретч-карты) с пин-кодом и номером карты.
Пример: Номер: 225-657
Пин-код: 1598632747525514

Схема работы с картами такова:
Пользователь выбирает в интернет-магазине товар, откладывает его в
корзину. Цена товара - 1 скретч-карта.
Как реализовать схему активации карты?

К примеру, пользователь жмёт "оплатить", появляется форма для номера
карты и пин-кода. Пользователь вбивает пин и номер, карта
активируется, товар куплен.

Как сделать активацию карт?
Есть идея хранить пин-коды карт на отдельном сервере в БД.
Когда происходит активация - с сайта идёт запрос на этот сервер, пины
и номера сривниваются, сервак возвращает true, а поле с пином и
номером в базе помечается, как заюзанное.

Как защитить бд от взлома?
Какие могут быть ошибки, которые позволят обмануть систему и украсть
или подделать пины?
Как вообще лучше реализовать такую схему?
 
Старый 19.07.2007, 16:28
Ссылки
Старый 19.07.2007, 16:43   #2
Цитата:
Как сделать активацию карт?
Есть идея хранить пин-коды карт на отдельном сервере в БД.
Когда происходит активация - с сайта идёт запрос на этот сервер, пины
и номера сривниваются, сервак возвращает true, а поле с пином и
номером в базе помечается, как заюзанное.
Идея совершенно правильная и логичная.

Цитата:
Как защитить бд от взлома? Какие могут быть ошибки, которые позволят обмануть систему и украсть или подделать пины?
Если перед отправкой запроса к БД проверить данные (а у нас они состоят только из цифр), то, в принципе, взломать будет сложно.

Но, чтобы усилить защиту следует сделать так:

1. Создать две хранимые процедуры: одна на переданные номер и пин карты выдаёт состояние: можно ли карту активировать (то есть то, что карта существует и ещё не активирована). Вторая хранимая процедура должна менять у карты с указанным номером состояние на «уже активирована». Каждая из функций должна полностью логировать свои действия (лог должен включать и IP пользователя).

2. Создать отдельного пользователя, который имеет доступ только к этим двум функциям и логиниться с сайта только под ним.

3. Для заполнения/правки базы использовать, понятное дело, отдельного пользователя.

Предлагаю в качестве СУБД использовать PostgreSQL — у него и с процедурами хорошо и с правами доступа.

deMone добавил [date]1184849347[/date]:
Если будут трудности с PostgreSQL — напиши, напишу
 
Старый 19.07.2007, 17:12   #3
Цитата:

1. Создать две хранимые процедуры: одна на переданные номер и пин карты выдаёт состояние: можно ли карту активировать (то есть то, что карта существует и ещё не активирована). Вторая хранимая процедура должна менять у карты с указанным номером состояние на «уже активирована». Каждая из функций должна полностью логировать свои действия (лог должен включать и IP пользователя).

2. Создать отдельного пользователя, который имеет доступ только к этим двум функциям и логиниться с сайта только под ним.

3. Для заполнения/правки базы использовать, понятное дело, отдельного пользователя.
Можешь поподробнее?
 
Старый 19.07.2007, 20:45   #4
Буду писать на примере PostgreSQL: я с ним постоянно работаю.

1. Создаём новую базу (шаблон — база postgres).

2. Назначаем базе язык Pl/PgSQL.
Код:
CREATE OR REPLACE FUNCTION "public"."plpgsql_call_handler" () RETURNS "pg_catalog"."language_handler" AS
'$libdir/plpgsql', 'plpgsql_call_handler'
LANGUAGE 'c' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER;

CREATE OR REPLACE FUNCTION "public"."plpgsql_validator" (oid) RETURNS "pg_catalog"."void" AS
'$libdir/plpgsql', 'plpgsql_validator'
LANGUAGE 'c' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER;

CREATE TRUSTED PROCEDURAL LANGUAGE "plpgsql"
  HANDLER "plpgsql_call_handler"
  VALIDATOR "plpgsql_validator";
3. Создаём таблицу:
Код:
CREATE TABLE "public"."cards" (
  "card_number" TEXT NOT NULL, -- Номер карты (поле взято TEXT, для знаков минуса в номере)
  "pin_code" TEXT, -- PIN-код
  "activated" BOOLEAN DEFAULT false, -- Карта уже была активирована?
  CONSTRAINT "cards_pkey" PRIMARY KEY("card_number")
) WITHOUT OIDS;
4. Создаём функцию, которая будет проверять существование скретч-карты и её неактивированность.
Код:
CREATE OR REPLACE FUNCTION "public"."card_exist" (card_num text, card_pin text) RETURNS boolean AS
$body$
DECLARE
	result	BOOLEAN		DEFAULT FALSE;	-- здесь будем хранить результат
BEGIN
	-- если хоть один из аргументов не задан - 
    -- возвращаем FALSE
	IF (card_num IS NULL OR card_pin IS NULL) THEN
    	RETURN FALSE;
    END IF;

	-- высматриваем, есть ли у нас неактивированная карта с
    -- указанными параметрами
    SELECT INTO result TRUE FROM cards WHERE card_number = card_num AND pin_code = card_pin AND activated = FALSE;

	-- если карта не найдена, то в result запишется NULL
    -- а нам нужен FALSE
    IF (result IS NULL) THEN
    	result = FALSE;
    END IF;

    RETURN result;
END;
$body$
LANGUAGE 'plpgsql' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER;
5. А теперь функцию, которая будет активировать карту (менять флаг activated).
Код:
CREATE OR REPLACE FUNCTION "public"."card_activate" (card_num text) RETURNS boolean AS
$body$
DECLARE
	status	BOOLEAN		DEFAULT FALSE;
BEGIN
	-- сначала проверяем, не была ли карта уже активирована
	SELECT INTO status TRUE FROM cards WHERE card_number = card_num AND activated = FALSE;

	-- если селект не пройдёт, значит уже активирована
	-- и возвращаем FALSE
	IF (status IS NULL) THEN
		RETURN FALSE;
	END IF;

	-- иначе активируем карту
	UPDATE cards SET activated = TRUE WHERE card_number = card_num;

	RETURN TRUE;
END;
$body$
LANGUAGE 'plpgsql' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER;
6. А теперь самое интересное: создаём пользователя, которым будем работать с этими функциями. Для этого входим в БД под пользователем «postgres» и выполняем запрос:
Код:
CREATE ROLE "card_reader" NOINHERIT LOGIN PASSWORD 'пароль';
7. И разрешаем ему пользоваться только нашими функциями (также, как читать и обновлять таблицу cards):
Код:
GRANT EXECUTE
  ON FUNCTION "public"."card_activate"(card_num text) TO "card_reader";
GRANT EXECUTE
  ON FUNCTION "public"."card_exist"(card_num text, card_pin text) TO "card_reader";
GRANT SELECT
  ON "public"."cards" TO "card_reader";
GRANT UPDATE
  ON "public"."cards" TO "card_reader";
8. Так как мы открыли доступ к обновлению базы данных (UPDATE приходится открыть, потому что иначе card_activate не сможет обновить таблицу), есть вероятность, что каким-то образом злоумышленник (получив доступ к системе) сможет сделать UPDATE и изменить PIN-код и номер карты в любой записи. А это уже плохо.

Мы, увы, не можем запретить изменение отдельных столбцов таблицы через систему прав PostgreSQL.

Поэтому здесь я предлагаю написать триггер, который просто будет запрещать изменение полей card_number и pin_code.

Это, конечно, помешает и основному пользователю системы (тому, который может добавлять записи), но я думаю, это можно и стерпеть (всегда можно удалить запись и создать по новой — основной пользователь это может, а card_reader — нет).
Код:
CREATE FUNCTION "cards_update_trigger" () RETURNS trigger AS
$body$
BEGIN
	IF (NEW.card_number != OLD.card_number OR NEW.pin_code != OLD.pin_code) THEN
		RAISE EXCEPTION 'Cannot update card number or PIN code';
	END IF;

	RETURN NEW;
END;
$body$
LANGUAGE 'plpgsql' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER;

CREATE TRIGGER "cards_update_trigger" BEFORE UPDATE 
ON "public"."cards" FOR EACH ROW 
EXECUTE PROCEDURE "cards_update_trigger"();
9. Ну всё, с базой покончено. А в PHP (ну, или другом языке) всё ещё проще: получаем номер карты и PIN-код из пользовательской формы, а дальше:
— выполнить card_exist() и проверить, что карта существует и ещё не активирована;
— выполнить card_activate(), если карта найдена;
— произвести остальные действия.

Ну, должно быть примерно так:
PHP код:
$r pg_query("SELECT card_exist('" $card_number "', '" $pin_code "') AS result");
$card pg_fetch_assoc($res); pg_free_result($res);

if (
$card['result'] == 't') {
    
// важная особенность: PostgreSQL возвращает булевые переменные в виде буквы "t" или "f"

    
$r pg_query("SELECT card_activate('" $card_number "') AS result");
    
$activate pg_fetch_assoc($res); pg_free_result($res);

    if (
$activate == 't') {
        
// всё активировалось отлично, производим остальные действия
    
} else {
        
// активировать не удалось
    
}
} else {
    
// карта или уже активирована, или вообще не существует

(я предположил, что $card_number и $pin_code уже проверены на корректность)
 
Старый 20.07.2007, 15:49   #5
А ты не в Москве живёшь?
 
Старый 20.07.2007, 16:24   #6
Нет. Я совсем не в Москве живу Я в Иркутске.
 
Старый 20.07.2007, 16:24
Закрытая тема




Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Создание интерактивной карты kav Технологии Flash 0 28.12.2010 08:46
Реализация карты на Flash (перемещение карты) ryasal Технологии Flash 1 09.11.2009 23:32
карты айпи seka Кальянная 12 31.01.2006 15:11
Опять я и опять помощь.... ivan341 Зал дебютантов 5 23.11.2005 10:23
стоимость Flash карты Diabolos Технологии Flash 4 17.08.2005 17:59


Текущее время: 17:35. Часовой пояс GMT +4.

Реклама на форуме Условия размещения рекламы
Биржа ссылок Заработай на сайте!
Дизайнерский форум