1 |
3 |
ahitrov@rambler.ru |
package Utils::Spam::SecretForm; |
2 |
|
|
|
3 |
|
|
use strict; |
4 |
|
|
use Digest::MD5; |
5 |
|
|
use Contenido::Globals; |
6 |
|
|
use Scalar::Util qw(blessed); |
7 |
|
|
|
8 |
|
|
# ��������� ������ ��� ������� � hidden-���� ����� |
9 |
|
|
# ��� ������������ �������� ������������. |
10 |
|
|
# extra - �������������� �������� ��� ��������� ������ |
11 |
|
|
# (� �������, ���� ������� ���������, ����� ���������� ��� �����) |
12 |
|
|
# �� ������ ���������� ������ �������� ��� ���������. |
13 |
|
|
sub generate { |
14 |
|
|
my %opts = @_; |
15 |
|
|
|
16 |
|
|
my ($start_time, $secret_code) = &get_secret_code(allow_generate_code => 1, memd => $opts{'memd'}); |
17 |
|
|
return unless $start_time && $secret_code; |
18 |
|
|
|
19 |
|
|
my $random = &get_random_string(5); |
20 |
|
|
# start secret code time | generate time | hash |
21 |
|
|
return $start_time.'|'.time().'|'.$random.'|'.Digest::MD5::md5_hex($start_time.$secret_code.$random.$opts{'extra'}); |
22 |
|
|
} |
23 |
|
|
|
24 |
|
|
# ��������� �������� hidden-���� ����� |
25 |
|
|
# secret - ���, ��� �������� |
26 |
|
|
# ttl - ����� ����� ��������� ���� |
27 |
|
|
# check_count - true �������� ���������� �� ������� ���������� ������������� |
28 |
|
|
sub validate { |
29 |
|
|
my %opts = @_; |
30 |
|
|
|
31 |
|
|
my $user_secret = $opts{'secret'}; |
32 |
|
|
my $ttl = $opts{'ttl'} || 3600; |
33 |
|
|
my $extra = $opts{'extra'}; |
34 |
|
|
my $check_count = $opts{'check_count'}; |
35 |
|
|
my $result = { is_valid => 1, is_expired => 0, count => 1 }; |
36 |
|
|
my $memd = blessed($opts{'memd'}) ? $opts{'memd'} : $keeper->MEMD(); |
37 |
|
|
|
38 |
|
|
return $result unless blessed($memd); |
39 |
|
|
|
40 |
|
|
# ���������� �� ������������ ������ |
41 |
|
|
my ($user_start_time, $user_generate_time, $user_random, $user_hash) = split(/\|/, $user_secret); |
42 |
|
|
|
43 |
|
|
# ������ � ��������� ������ |
44 |
|
|
my ($start_time, $secret_code) = &get_secret_code(time => $user_start_time, memd => $memd); |
45 |
|
|
|
46 |
|
|
# ���� ��� �� �������� ��������� ����� ��������� |
47 |
|
|
return $result if !defined($start_time) && !defined($secret_code); |
48 |
|
|
|
49 |
|
|
if (Digest::MD5::md5_hex($start_time.$secret_code.$user_random.$extra) ne $user_hash) { |
50 |
|
|
$result->{'is_valid'} = 0; |
51 |
|
|
} |
52 |
|
|
|
53 |
|
|
if ($result->{'is_valid'} && (($user_generate_time-$start_time > 3600) |
54 |
|
|
|| (time()-$user_generate_time > $ttl)) |
55 |
|
|
) { |
56 |
|
|
$result->{'is_expired'} = 1; |
57 |
|
|
} |
58 |
|
|
|
59 |
|
|
# ���� ���������� �������� �� ��������� ������������� |
60 |
|
|
# ������ � ���������� ������������� ���������� ��������� � ���� |
61 |
|
|
if ($result->{'is_valid'} && !$result->{'is_expired'} && $check_count) { |
62 |
|
|
|
63 |
|
|
$result->{'count'} = $memd->incr('usersecret|'.$user_secret, 1) if $memd; |
64 |
|
|
|
65 |
|
|
unless ($result->{'count'}) { |
66 |
|
|
$memd->add('usersecret|'.$user_secret, 1, $ttl) if $memd; |
67 |
|
|
$result->{'count'} = 1; |
68 |
|
|
} |
69 |
|
|
} |
70 |
|
|
|
71 |
|
|
return $result; |
72 |
|
|
} |
73 |
|
|
|
74 |
|
|
# ���������, ������� ���������� true ��� false � ����������� �� ����������, �������������� |
75 |
|
|
# � ���������� ������������� |
76 |
|
|
sub is_valid_secret { |
77 |
|
|
my %opts = @_; |
78 |
|
|
|
79 |
|
|
my $validate = &validate(%opts); |
80 |
|
|
|
81 |
|
|
if ($validate->{'is_valid'} && !$validate->{'is_expired'} |
82 |
|
|
&& (!$opts{'check_count'} || ($opts{'check_count'} && $validate->{'count'} == 1))) |
83 |
|
|
{ |
84 |
|
|
return 1; |
85 |
|
|
} |
86 |
|
|
|
87 |
|
|
return undef; |
88 |
|
|
} |
89 |
|
|
|
90 |
|
|
# ��������� ��������� � ��������� ��� ������������� |
91 |
|
|
# ���������� ����. ��������� ���� ����������� � ������� �����. |
92 |
|
|
# time - ��� ���������� ������� ������ ���������� �� ��� ������ ��� |
93 |
|
|
# allow_generate_code - ��������� ������������ ���, ���� �� �� ������ |
94 |
|
|
sub get_secret_code { |
95 |
|
|
my %opts = @_; |
96 |
|
|
|
97 |
|
|
# ������� ������� memcached �������� ������������ |
98 |
|
|
# �������� ����������������� |
99 |
|
|
my $memd = blessed($opts{'memd'}) ? $opts{'memd'} : $keeper->MEMD(); |
100 |
|
|
return unless blessed($memd); |
101 |
|
|
|
102 |
|
|
my $time = abs(int($opts{'time'})); |
103 |
|
|
my $now_time = time(); |
104 |
|
|
|
105 |
|
|
# ����� � ����������� �� ������ ���� |
106 |
|
|
unless ($time) { |
107 |
|
|
$time = $now_time; |
108 |
|
|
$time = $time - ($time % 3600); |
109 |
|
|
} |
110 |
|
|
|
111 |
|
|
my $cache_key = 'secret_code|'.$time; |
112 |
|
|
|
113 |
|
|
my $secret_code = $memd->get($cache_key); |
114 |
|
|
return ($time, $secret_code) if $secret_code; |
115 |
|
|
|
116 |
|
|
if ($opts{'allow_generate_code'}) { |
117 |
|
|
$secret_code = &get_random_string(10); |
118 |
|
|
$memd->set($cache_key, $secret_code); |
119 |
|
|
} |
120 |
|
|
|
121 |
|
|
return ($time, $secret_code); |
122 |
|
|
} |
123 |
|
|
|
124 |
|
|
|
125 |
|
|
# ��������� ��������� ������ |
126 |
|
|
# length - ����� ������ |
127 |
|
|
sub get_random_string { |
128 |
|
|
my $length = shift; |
129 |
|
|
$length = 10 unless $length && $length =~ /^\d+$/; |
130 |
|
|
|
131 |
|
|
my $random_chars = 'abcdefghijklmnopqrstuvwxyz1234567890'; |
132 |
|
|
my $random_chars_length = length($random_chars); |
133 |
|
|
|
134 |
|
|
my $string = ''; |
135 |
|
|
for (1..$length) { |
136 |
|
|
$string .= substr($random_chars, int(rand($random_chars_length)), 1); |
137 |
|
|
} |
138 |
|
|
|
139 |
|
|
return $string; |
140 |
|
|
} |
141 |
|
|
|
142 |
|
|
|
143 |
|
|
1; |
144 |
|
|
__END__ |
145 |
|
|
|
146 |
|
|
=head1 NAME |
147 |
|
|
|
148 |
|
|
Utils::Spam::SecretForm - ������� ��������� � �������� ��������� ������ ��� web-���� |
149 |
|
|
|
150 |
|
|
=head1 SYNOPSIS |
151 |
|
|
|
152 |
|
|
���������: |
153 |
|
|
<input type="hidden" name="secret" value="<% Utils::Spam::SecretForm::generate() %>"> |
154 |
|
|
|
155 |
|
|
��������: |
156 |
|
|
my $validate = Utils::Spam::SecretForm::validate( secret => $ARGS{'secret'}, check_count => 0|1 ); |
157 |
|
|
if ($validate->{'is_valid'} && !$validate->{'is_expired'}) { |
158 |
|
|
allowed method |
159 |
|
|
} |
160 |
|
|
|
161 |
|
|
|
162 |
|
|
=head1 DESCRIPTION |
163 |
|
|
|
164 |
|
|
� ������� javascript ���������� ������ �������� http-������� get � post �������. |
165 |
|
|
����� �������� a.html ��������: |
166 |
|
|
<form method=post action=http://www.rambler.ru/post.html name="b"> |
167 |
|
|
<input type="text" name="text"> |
168 |
|
|
<input name="submit" type="submit" value="submit"> |
169 |
|
|
</form> |
170 |
|
|
<script> |
171 |
|
|
document.b.submit.click(); |
172 |
|
|
</script> |
173 |
|
|
|
174 |
|
|
����� �������, �������, �������� �� �������� a.html, �������� ������ �����. |
175 |
|
|
��� ������ � ������ ����� ���� ������� ������������ ������ ������. |
176 |
|
|
|
177 |
|
|
������� ������: ��� � ��� ������������ ��������� ��������� ������, ������� �������� � ���� �� ����� secret_code|�����_���������. |
178 |
|
|
���� ��� �� ��������, ��������� �������� ������� ��� ������ ���� ��������. |
179 |
|
|
������������ ��� ��������� ����� �������� ����� ��� � hidden ����, ������� ������� �� ���� ������: |
180 |
|
|
1) ����� ��������� ��������� ������ |
181 |
|
|
2) ����� ������ ������ ������������ |
182 |
|
|
3) ��������� ������ |
183 |
|
|
4) md5_hex( ����� ������ ������ ������������ . ��������� ������ . ��������� ������) |
184 |
|
|
��� ����������� ����������� hidden-��������� ���������� ��������� ��������� ������ �� ���� secret_code|�����_���������, ��������� md5_hex(������� . ���������� ������) � �������� ������� ������� ��������� ���� � �������� �������. |
185 |
|
|
����� ������� �������� ������ �� ������������������� ��������. ��� ������ �� ���������� ������������� ���� ���������� ������������ �������� check_count, � ����������� �� �������� � ���������� ����������� �������� ���������� ������������� ���� (����� ������� ������������� count = 1). |
186 |
|
|
��� ��������� ������ ���������� ����������� ���������� extra ��������� ��� ��������� hidden-����, �������� ��� ������������ ������������, ��� ����� ���� ����� ��� ������. �� ���������� �� �������� ���������� ���� �������� �� ����� ���������. |
187 |
|
|
|