230
|
1 package IMPL::Web::Handler::SecureCookie;
|
196
|
2 use strict;
|
|
3
|
230
|
4
|
196
|
5 use Digest::MD5 qw(md5_hex);
|
230
|
6 use IMPL::Const qw(:prop);
|
|
7 use IMPL::Security::Auth qw(:Const GenSSID);
|
|
8 use IMPL::declare {
|
|
9 require => {
|
|
10 SecurityContext => 'IMPL::Security::Context',
|
|
11 User => 'IMPL::Security::User',
|
|
12 AuthSimple => 'IMPL::Security::Auth::Simple',
|
|
13 },
|
|
14 base => {
|
|
15 'IMPL::Object' => undef,
|
|
16 'IMPL::Object::Autofill' => '@_',
|
|
17 'IMPL::Object::Serializable' => undef
|
|
18 },
|
|
19 props => [
|
|
20 salt => PROP_RO,
|
|
21 manager => PROP_RO,
|
|
22 _cookies => PROP_RW
|
|
23 ]
|
|
24 };
|
196
|
25
|
|
26 sub CTOR {
|
|
27 my ($this) = @_;
|
|
28
|
|
29 $this->salt('DeadBeef') unless $this->salt;
|
|
30 }
|
|
31
|
230
|
32 sub Invoke {
|
196
|
33 my ($this,$action,$nextHandler) = @_;
|
|
34
|
230
|
35 return unless $nextHandler;
|
|
36
|
|
37 my $context;
|
196
|
38
|
230
|
39
|
|
40 my $sid = $action->cookie('sid',qr/(\w+)/);
|
|
41 my $cookie = $action->cookie('sdata',qr/(\w+)/);
|
|
42 my $sign = $action->cookie('sign',qw/(\w+)/);
|
196
|
43
|
230
|
44 if (
|
|
45 $sid and
|
|
46 $cookie and
|
|
47 $sign and
|
|
48 $sign eq md5_hex(
|
|
49 $this->salt,
|
|
50 $sid,
|
|
51 $cookie,
|
|
52 $this->salt
|
|
53 )
|
|
54 ) {
|
|
55 # TODO: add a DefferedProxy to deffer a request to a data source
|
|
56 if ( $context = $this->manager->GetSession($sid) ) {
|
196
|
57
|
230
|
58 if ( eval { $context->auth->isa(AuthSimple) } ) {
|
|
59 my ($result,$challenge) = $context->auth->DoAuth($cookie);
|
|
60
|
|
61 $action->manager->SaveSession($context);
|
|
62
|
|
63 if ($result == AUTH_FAIL) {
|
|
64 $context = undef;
|
|
65 }
|
196
|
66 }
|
|
67 }
|
230
|
68
|
196
|
69 }
|
230
|
70
|
|
71 $context = SecurityContext->new(principal => User->nobody, authority => $this);
|
|
72
|
|
73 my $httpResponse = $context->Impersonate($nextHandler);
|
|
74
|
|
75 $this->WriteResponse($httpResponse);
|
|
76
|
|
77 }
|
|
78
|
|
79 sub CreateContext {
|
|
80 my ($this,$user,$auth,$roles) = @_;
|
|
81
|
|
82 my $sid = GenSSID();
|
|
83 my $cookie = GenSSID();
|
|
84
|
|
85 $this->_cookies({
|
|
86 sid => $sid,
|
|
87 sdata => $cookie
|
|
88 })
|
|
89
|
|
90 my $context = $this->$manager->CreateSession(
|
|
91 sessionId => $sid,
|
|
92 principal => $user,
|
|
93 auth => AuthSimple->(password => $cookie),
|
|
94 authority => $this,
|
|
95 assignedRoles => $roles
|
|
96 );
|
|
97
|
|
98 $context->Apply();
|
|
99
|
|
100 return $context;
|
196
|
101 }
|
|
102
|
|
103 sub WriteResponse {
|
230
|
104 my ($this,$response) = @_;
|
|
105
|
|
106 if (my $data $this->_cookies) {
|
196
|
107
|
230
|
108 my $sign = md5_hex(
|
|
109 $this->salt,
|
|
110 $data->{sid},
|
|
111 $data->{sdata},
|
|
112 $this->salt
|
|
113 );
|
|
114
|
|
115 $response->cookies->{sid} = $data->{sid};
|
|
116 $response->cookies->{sdata} = $data->{sdata};
|
|
117 $response->cookies->{sign} = $sign;
|
|
118 }
|
196
|
119 }
|
|
120
|
|
121 1;
|
|
122
|
|
123 __END__
|
|
124
|
|
125 =pod
|
|
126
|
|
127 =head1 NAME
|
|
128
|
230
|
129 C<IMPL::Web::Handler::SecureCookie>
|
196
|
130
|
|
131 =head1 DESCRIPTION
|
|
132
|
|
133 Возобновляет сессию пользователя на основе информации переданной через Cookie.
|
|
134
|
|
135 Использует механизм подписи информации для проверки верности входных данных перед
|
|
136 началом каких-либо действий.
|
|
137
|
|
138 Данный обработчик возвращает результат выполнения следдующего обработчика.
|
|
139
|
230
|
140
|
|
141
|
196
|
142 =head1 MEMBERS
|
|
143
|
|
144 =over
|
|
145
|
|
146 =item C<[get,set] salt>
|
|
147
|
|
148 Скаляр, использующийся для подписи данных.
|
|
149
|
|
150 =back
|
|
151
|
|
152 =cut
|