在Postgres High(PSD 9.6)中,书呆子和欢乐合唱俱乐部处于一场奇怪的共同战争中。书呆子策划了对欢乐俱乐部的秘密计划。欢乐合唱团以愉快的歌曲回应。
如果书呆子懦弱的话,欢乐合唱团永远不会回应。同样地,书呆子只是试图摆脱欢乐合唱团,所以如果欢乐合唱俱乐部没有回应,那么书呆子实际上并没有调用他们的秘密计划。作为首席程序员,我的工作是确保只有一次可能的书呆子反叛尝试同时发生。我还必须确保两个书呆子都成功,欢乐俱乐部成功或者都没有成功。但那些 麻烦的书呆子,总是尝试sql注入攻击。也要防止这样做。正如Postgres High的所有优秀领导者所做的那样,我们用SQL编写课程计划。
课程计划:
begin;
-- stop race conditions with a hall monitor
select from semaphore where name = 'hall_monitor' for update;
prepare nerd_rebellion (
text, -- secret_mission
date -- when_we_strike
) as
update ultimate_plan
set secret_mission = $1
where when_we_strike = $2;
prepare glee_club_counterstrike (
text, -- happy_song
boolean -- kill_them_with_love
) as
insert into song_therapy (
happy_song,
kill_them_with_love
) values (
$1,
$2
)
execute nerd_rebellion(
'Nerds do stuff like this ; drop table song_therapy --f you glee club',
'2017-01-01'
);
execute glee_club_counterstrike(
'god_bless_america',
true
);
-- let us never speak of this again ...
deallocate nerd_rebellion
deallocate glee_club_counterstrike
-- all done. Release the hall monitor
commit;
天哪,这对校长来说很重要。我们的课程时间很短,我们准备和解除了所有这些。啊。真的切入我的咖啡和甜甜圈时间。但我需要在单个事务中包装多个语句并使用信号量进行序列化。不能在SQL注入上做出妥协。我没有看到更简单的解决方案。你呢?
答案 0 :(得分:2)
你没有确定书呆子是否成功。书呆子可能会爆发(UPDATE
可能没有排),欢乐合唱团无论如何都会唱歌。
您可以使用数据修改CTE或plpgsql函数链接这两个命令,您可以在其中使插入取决于更新是否成功。
这是校长可能使用的工具:
CREATE OR REPLACE FUNCTION nerd_strike(
_secret_mission text
, _when_we_strike date
, _happy_song text
, _kill_them_with_love boolean
) RETURNS void AS
$func$
BEGIN
SELECT FROM semaphore WHERE name = 'hall_monitor' FOR UPDATE;
UPDATE ultimate_plan
SET secret_mission = _secret_mission
WHERE when_we_strike = _when_we_strike;
IF FOUND THEN -- only if update actually succeeded
INSERT INTO song_therapy (happy_song, kill_them_with_love)
VALUES (_happy_song, _kill_them_with_love);
END IF;
END
$func$ LANGUAGE plpgsql;
呼叫:
SELECT nerd_strike('Nerds do stuff like this ; drop table song_therapy --f you glee club'
, '2017-01-01'
, 'god_bless_america'
, true);
函数是原子的,所以一切都发生了或者从未发生过 参数作为 values 传递(非常类似于预处理语句),因此没有机会进行SQL注入。
相关: